BUG#: 7626
[tpot/pegasus/.git] / src / Pegasus / IndicationService / IndicationService.cpp
1 //%LICENSE////////////////////////////////////////////////////////////////
2 //
3 // 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 //
10 // 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 //
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // 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 //
28 //////////////////////////////////////////////////////////////////////////
29 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include <Pegasus/Common/Config.h>
33 #include <Pegasus/Common/Constants.h>
34 #include <Pegasus/Common/CIMInstance.h>
35 #include <Pegasus/Common/ArrayInternal.h>
36 #include <Pegasus/Common/CIMDateTime.h>
37 #include <Pegasus/Common/CIMProperty.h>
38 #include <Pegasus/Common/MessageQueue.h>
39 #include <Pegasus/Common/System.h>
40 #include <Pegasus/Common/Tracer.h>
41 #include <Pegasus/Common/XmlWriter.h>
42 #include <Pegasus/Common/PegasusVersion.h>
43 #include <Pegasus/Common/AcceptLanguageList.h>
44 #include <Pegasus/Common/ContentLanguageList.h>
45 #include <Pegasus/Common/LanguageParser.h>
46 #include <Pegasus/Common/OperationContextInternal.h>
47 #include <Pegasus/Common/MessageLoader.h>
48 #include <Pegasus/Common/String.h>
49
50 #include <Pegasus/General/IndicationFormatter.h>
51 #include <Pegasus/General/Guid.h>
52 #ifdef PEGASUS_INDICATION_PERFINST
53 #include <Pegasus/General/Stopwatch.h>
54 #endif
55
56 #include <Pegasus/Server/ProviderRegistrationManager/\
57 ProviderRegistrationManager.h>
58 #include <Pegasus/Query/QueryExpression/QueryExpression.h>
59 #include <Pegasus/Query/QueryCommon/QueryException.h>
60 #include <Pegasus/Repository/RepositoryQueryContext.h>
61
62 #include "IndicationConstants.h"
63 #include "SubscriptionRepository.h"
64 #include "SubscriptionTable.h"
65 #include "IndicationService.h"
66
67
68 PEGASUS_USING_STD;
69
70 PEGASUS_NAMESPACE_BEGIN
71
72 //
73 // Message constants
74 //
75
76 static const char _MSG_PROPERTY_KEY[] =
77    "IndicationService.IndicationService._MSG_PROPERTY";
78 static const char _MSG_PROPERTY[] = "The required property $0 is missing.";
79
80 static const char _MSG_NO_PROVIDERS_KEY[] =
81     "IndicationService.IndicationService._MSG_NO_PROVIDERS";
82 static const char _MSG_NO_PROVIDERS[] =
83     "No providers are capable of servicing the subscription.";
84
85 static const char _MSG_INVALID_TYPE_FOR_PROPERTY_KEY[] =
86     "IndicationService.IndicationService._MSG_INVALID_TYPE_FOR_PROPERTY";
87 static const char _MSG_INVALID_TYPE_FOR_PROPERTY[] =
88     "The value of type $0 is not valid for property $1.";
89
90 static const char _MSG_INVALID_TYPE_ARRAY_OF_FOR_PROPERTY_KEY[] =
91     "IndicationService.IndicationService."
92         "_MSG_INVALID_TYPE_ARRAY_OF_FOR_PROPERTY";
93 static const char _MSG_INVALID_TYPE_ARRAY_OF_FOR_PROPERTY[] =
94     "The value of an array of type $0 is not valid for property $1.";
95
96 static const char _MSG_INVALID_VALUE_FOR_PROPERTY_KEY[] =
97     "IndicationService.IndicationService._MSG_INVALID_VALUE_FOR_PROPERTY";
98 static const char _MSG_INVALID_VALUE_FOR_PROPERTY[] =
99     "The value $0 is not valid for property $1.";
100
101 static const char _MSG_UNSUPPORTED_VALUE_FOR_PROPERTY_KEY[] =
102     "IndicationService.IndicationService._MSG_UNSUPPORTED_VALUE_FOR_PROPERTY";
103 static const char _MSG_UNSUPPORTED_VALUE_FOR_PROPERTY[] =
104     "The value $0 is not supported for property $1.";
105
106 static const char _MSG_CLASS_NOT_SERVED_KEY[] =
107     "IndicationService.IndicationService._MSG_CLASS_NOT_SERVED";
108 static const char _MSG_CLASS_NOT_SERVED[] =
109     "The specified class is not serviced by the CIM Indication service.";
110
111 static const char _MSG_INVALID_INSTANCES_KEY[] =
112     "IndicationService.IndicationService."
113         "INVALID_SUBSCRIPTION_INSTANCES_IGNORED";
114 static const char _MSG_INVALID_INSTANCES[] =
115     "One or more subscription instances are not valid and are ignored.";
116
117 static const char _MSG_PROVIDER_NO_LONGER_SERVING_KEY[] =
118     "IndicationService.IndicationService._MSG_PROVIDER_NO_LONGER_SERVING";
119 static const char _MSG_PROVIDER_NO_LONGER_SERVING[] =
120     "Provider ($0) is no longer serving subscription ($1) in namespace $2";
121
122 static const char _MSG_PROVIDER_NOW_SERVING_KEY[] =
123     "IndicationService.IndicationService._MSG_PROVIDER_NOW_SERVING";
124 static const char _MSG_PROVIDER_NOW_SERVING[] =
125     "Provider ($0) is now serving subscription ($1) in namespace $2";
126
127 static const char _MSG_NO_PROVIDER_KEY[] =
128     "IndicationService.IndicationService._MSG_NO_PROVIDER";
129 static const char _MSG_NO_PROVIDER[] =
130     "Subscription ($0) in namespace $1 has no provider";
131
132 static const char _MSG_STATE_CHANGE_FAILED_KEY[] =
133     "IndicationService.IndicationService.STATE_CHANGE_FAILED";
134 static const char _MSG_STATE_CHANGE_FAILED[] =
135     "The requested state change failed : $0. Current IndicationService"
136         " EnabledState : $1, HealthState : $2.";
137
138 // ATTN-RK-20020730: Temporary hack to fix Windows build
139 Boolean ContainsCIMName(const Array<CIMName>& a, const CIMName& x)
140 {
141     Uint32 n = a.size();
142
143     for (Uint32 i = 0; i < n; i++)
144     {
145         if (a[i].equal(x))
146             return true;
147     }
148
149     return false;
150 }
151
152 Mutex IndicationService::_mutex;
153 Uint16 IndicationService::_enabledState = _ENABLEDSTATE_DISABLED;
154 Uint16 IndicationService::_healthState = _HEALTHSTATE_OK;
155
156 /**
157     See CIM_EnabledLogicalElement.RequestStateChange() method for return codes
158     and CIM_EnabledLogicalElement.EnabledState property for  service states.
159
160     ATTN: Currently very few states are supported and the following utility
161     functions are  hard coded to return service states directly. Write a
162     generic function to get values  from ValueMap independent of class.
163 */
164 String _getEnabledStateString(Uint32 code)
165 {
166     // Check for service states
167     switch(code)
168     {
169         case _ENABLEDSTATE_ENABLED:
170             return String("Enabled");
171         case _ENABLEDSTATE_DISABLED:
172             return String("Disabled");
173         case _ENABLEDSTATE_SHUTTINGDOWN:
174             return String("Shutting Down");
175         case _ENABLEDSTATE_STARTING:
176             return String("Starting");
177     }
178     PEGASUS_ASSERT(false); // Never reach to unknown state at present.
179
180     return String("Unknown");
181 }
182
183 String _getHealthStateString(Uint32 code)
184 {
185     // Service health states
186     switch(code)
187     {
188         case _HEALTHSTATE_OK:
189             return String("OK");
190         case _HEALTHSTATE_DEGRADEDWARNING:
191             return String("Degraded/Warning");
192     }
193     PEGASUS_ASSERT(false); // Never reach to unknown state at present.
194
195     return String("Unknown");
196 }
197
198 IndicationService::IndicationService(
199     CIMRepository* repository,
200     ProviderRegistrationManager* providerRegManager)
201     : MessageQueueService(
202           PEGASUS_QUEUENAME_INDICATIONSERVICE),
203       _providerRegManager(providerRegManager),
204       _cimRepository(repository)
205 {
206     _enableSubscriptionsForNonprivilegedUsers = false;
207     _authenticationEnabled = true;
208
209     try
210     {
211         // Determine the value for the configuration parameter
212         // enableSubscriptionsForNonprivilegedUsers
213         ConfigManager* configManager = ConfigManager::getInstance();
214
215         if (ConfigManager::parseBooleanValue(
216             configManager->getCurrentValue("enableAuthentication")))
217         {
218             _enableSubscriptionsForNonprivilegedUsers =
219                 ConfigManager::parseBooleanValue(
220                     configManager->getCurrentValue(
221                         "enableSubscriptionsForNonprivilegedUsers"));
222         }
223         else
224         {
225             _authenticationEnabled = false;
226             // Authentication needs to be enabled to perform authorization
227             // tests.
228             _enableSubscriptionsForNonprivilegedUsers = true;
229         }
230      }
231      catch (...)
232      {
233         // If there is an error reading the configuration file then
234         // the value of _enableSubscriptionsForNonprivilegedUsers will
235         // default to false (i.e., the more restrictive security
236         // setting.
237         PEG_TRACE_CSTRING(TRC_INDICATION_SERVICE, Tracer::LEVEL2,
238             "Failure attempting to read configuration parameters during "
239                 "initialization.");
240      }
241
242     PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
243         "Value of _enableSubscriptionsForNonprivilegedUsers is %d",
244         _enableSubscriptionsForNonprivilegedUsers));
245
246     try
247     {
248         // Create IndicationsProfileInstance Repository
249 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
250         _indicationServiceConfiguration.reset(
251             new IndicationServiceConfiguration(_cimRepository));
252 #endif
253         // Initialize the Indication Service
254         _initialize();
255     }
256     catch (Exception& e)
257     {
258         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL1,
259            "Exception caught in attempting to "
260            "initialize Indication Service: %s",
261            (const char*)e.getMessage().getCString()));
262         _healthState = _HEALTHSTATE_DEGRADEDWARNING;
263     }
264
265 }
266
267 IndicationService::~IndicationService()
268 {
269 }
270
271 Uint16 IndicationService::getHealthState()
272 {
273     return _healthState;
274 }
275
276 Uint16 IndicationService::getEnabledState()
277 {
278     return _enabledState;
279 }
280
281 void IndicationService::_handle_async_request(AsyncRequest *req)
282 {
283     if (req->getType() == ASYNC_CIMSERVICE_STOP)
284     {
285         //
286         //  Call _terminate
287         //
288         _terminate();
289
290         handle_CimServiceStop(static_cast<CimServiceStop *>(req));
291     }
292     else if (req->getType() == ASYNC_CIMSERVICE_START)
293     {
294         handle_CimServiceStart(static_cast<CimServiceStart *>(req));
295     }
296     else if (req->getType() == ASYNC_ASYNC_LEGACY_OP_START)
297     {
298         try
299         {
300             Message* legacy =
301                 static_cast<AsyncLegacyOperationStart *>(req)->get_action();
302             legacy->put_async(req);
303
304             handleEnqueue(legacy);
305         }
306         catch(Exception& )
307         {
308             PEG_TRACE_CSTRING(TRC_INDICATION_SERVICE, Tracer::LEVEL1,
309                 "Caught Exception in IndicationService while handling a "
310                     "wrapped legacy message ");
311                 _make_response(req, async_results::CIM_NAK);
312         }
313
314         return;
315     }
316     else
317         MessageQueueService::_handle_async_request(req);
318 }
319
320 void IndicationService::handleEnqueue(Message* message)
321 {
322 #ifdef PEGASUS_INDICATION_PERFINST
323     Stopwatch stopWatch;
324
325     stopWatch.start();
326 #endif
327     CIMRequestMessage* cimRequest = dynamic_cast<CIMRequestMessage *>(message);
328     PEGASUS_ASSERT(cimRequest);
329
330     // Set the client's requested language into this service thread.
331     // This will allow functions in this service to return messages
332     // in the correct language.
333     cimRequest->updateThreadLanguages();
334
335     try
336     {
337         if (_enabledState != _ENABLEDSTATE_ENABLED)
338         {
339             _handleCimRequestWithServiceNotEnabled(message);
340         }
341         else
342         {
343             _handleCimRequest(message);
344         }
345     }
346     catch (CIMException& e)
347     {
348         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL1,
349             "CIMException caught in IndicationService::handleEnqueue: %s",
350             (const char*)e.getMessage().getCString()));
351         CIMResponseMessage* response = cimRequest->buildResponse();
352         response->cimException = e;
353         _enqueueResponse(cimRequest, response);
354     }
355     catch (Exception& e)
356     {
357         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL1,
358             "Exception caught in IndicationService::handleEnqueue: %s",
359             (const char*)e.getMessage().getCString()));
360         CIMResponseMessage* response = cimRequest->buildResponse();
361         response->cimException =
362             PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, e.getMessage());
363         _enqueueResponse(cimRequest, response);
364     }
365     catch (...)
366     {
367         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL1,
368             "Unknown exception caught in IndicationService::handleEnqueue."));
369         CIMResponseMessage* response = cimRequest->buildResponse();
370         response->cimException = PEGASUS_CIM_EXCEPTION_L(
371             CIM_ERR_FAILED,
372             MessageLoaderParms(
373                 "IndicationService.IndicationService.UNKNOWN_ERROR",
374                 "Unknown Error"));
375         _enqueueResponse(cimRequest, response);
376     }
377
378 #ifdef PEGASUS_INDICATION_PERFINST
379     stopWatch.stop();
380
381     PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
382         "%s: %.3f seconds",
383         MessageTypeToString(message->getType()),
384         stopWatch.getElapsed()));
385 #endif
386
387    delete message;
388 }
389
390 void IndicationService::_handleCimRequest(Message *message)
391 {
392     switch(message->getType())
393     {
394         case CIM_GET_INSTANCE_REQUEST_MESSAGE:
395             _handleGetInstanceRequest(message);
396         break;
397
398         case CIM_ENUMERATE_INSTANCES_REQUEST_MESSAGE:
399             _handleEnumerateInstancesRequest(message);
400             break;
401
402         case CIM_ENUMERATE_INSTANCE_NAMES_REQUEST_MESSAGE:
403             _handleEnumerateInstanceNamesRequest(message);
404             break;
405
406         case CIM_CREATE_INSTANCE_REQUEST_MESSAGE:
407             _handleCreateInstanceRequest(message);
408             break;
409
410         case CIM_MODIFY_INSTANCE_REQUEST_MESSAGE:
411             _handleModifyInstanceRequest(message);
412             break;
413
414         case CIM_DELETE_INSTANCE_REQUEST_MESSAGE:
415             _handleDeleteInstanceRequest(message);
416             break;
417
418         case CIM_PROCESS_INDICATION_REQUEST_MESSAGE:
419             _handleProcessIndicationRequest(message);
420             break;
421
422         case CIM_NOTIFY_PROVIDER_REGISTRATION_REQUEST_MESSAGE:
423             _handleNotifyProviderRegistrationRequest(message);
424             break;
425
426         case CIM_NOTIFY_PROVIDER_TERMINATION_REQUEST_MESSAGE:
427             _handleNotifyProviderTerminationRequest(message);
428             break;
429
430         case CIM_NOTIFY_PROVIDER_ENABLE_REQUEST_MESSAGE:
431             _handleNotifyProviderEnableRequest(message);
432             break;
433
434         case CIM_NOTIFY_PROVIDER_FAIL_REQUEST_MESSAGE:
435             _handleNotifyProviderFailRequest(message);
436             break;
437
438 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
439         case CIM_INVOKE_METHOD_REQUEST_MESSAGE:
440             _handleInvokeMethodRequest(message);
441             break;
442 #endif
443
444         default:
445             CIMRequestMessage* cimRequest =
446                 dynamic_cast<CIMRequestMessage *>(message);
447             //
448             //  A message type not supported by the Indication Service
449             //  Should not reach here
450             //
451             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL1,
452                 "IndicationService::_handleCimRequest rcv'd unsupported "
453                     "message of type %s.",
454                 MessageTypeToString(message->getType())));
455
456             // Note: not setting Content-Language in the response
457             CIMResponseMessage* response = cimRequest->buildResponse();
458             response->cimException = PEGASUS_CIM_EXCEPTION_L(
459                 CIM_ERR_NOT_SUPPORTED,
460                 MessageLoaderParms(
461                     "IndicationService.IndicationService."
462                         "UNSUPPORTED_OPERATION",
463                     "The requested operation is not supported or not "
464                         "recognized by the indication service."));
465
466             _enqueueResponse(cimRequest, response);
467     }
468 }
469
470 void IndicationService::_handleCimRequestWithServiceNotEnabled(
471     Message *message)
472 {
473     Boolean requestHandled = false;
474     CIMRequestMessage* cimRequest = dynamic_cast<CIMRequestMessage *>(message);
475
476 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
477     requestHandled = true;
478     switch(message->getType())
479     {
480         case CIM_INVOKE_METHOD_REQUEST_MESSAGE:
481             _handleInvokeMethodRequest(message);
482             break;
483         case CIM_NOTIFY_PROVIDER_REGISTRATION_REQUEST_MESSAGE:
484         case CIM_NOTIFY_PROVIDER_TERMINATION_REQUEST_MESSAGE:
485         case CIM_NOTIFY_PROVIDER_ENABLE_REQUEST_MESSAGE:
486         case CIM_NOTIFY_PROVIDER_FAIL_REQUEST_MESSAGE:
487             _enqueueResponse(cimRequest, cimRequest->buildResponse());
488             break;
489
490         case CIM_PROCESS_INDICATION_REQUEST_MESSAGE:
491             _handleProcessIndicationRequest(message);
492             break;
493
494         // Handle only CIM_IndicationService class operations.
495         case CIM_GET_INSTANCE_REQUEST_MESSAGE:
496             {
497                 CIMGetInstanceRequestMessage *request =
498                     (CIMGetInstanceRequestMessage*)message;
499                 if (request->className.equal(
500                     PEGASUS_CLASSNAME_CIM_INDICATIONSERVICE))
501                 {
502                     _handleGetInstanceRequest(message);
503                 }
504                 else
505                 {
506                     requestHandled = false;
507                 }
508             }
509             break;
510         case CIM_ENUMERATE_INSTANCES_REQUEST_MESSAGE:
511             {
512                 CIMEnumerateInstancesRequestMessage *request =
513                     (CIMEnumerateInstancesRequestMessage*)message;
514                 if (request->className.equal(
515                     PEGASUS_CLASSNAME_CIM_INDICATIONSERVICE))
516                 {
517                     _handleEnumerateInstancesRequest(message);
518                 }
519                 else
520                 {
521                     requestHandled = false;
522                 }
523             }
524             break;
525
526         case CIM_ENUMERATE_INSTANCE_NAMES_REQUEST_MESSAGE:
527             {
528                 CIMEnumerateInstanceNamesRequestMessage *request =
529                     (CIMEnumerateInstanceNamesRequestMessage*)message;
530                 if (request->className.equal(
531                     PEGASUS_CLASSNAME_CIM_INDICATIONSERVICE))
532                 {
533                     _handleEnumerateInstanceNamesRequest(message);
534                 }
535                 else
536                 {
537                     requestHandled = false;
538                 }
539             }
540             break;
541         default:
542             requestHandled = false;
543             break;
544     }
545 #endif
546
547     if (!requestHandled)
548     {
549         Logger::put_l(
550             Logger::STANDARD_LOG,
551             System::CIMSERVER,
552             Logger::WARNING,
553             MessageLoaderParms(
554                 "IndicationService.IndicationService."
555                     "CANNOT_EXECUTE_REQUEST",
556                 "The requested operation cannot be executed."
557                     " IndicationService EnabledState : $0.",
558                 _getEnabledStateString(_enabledState)));
559
560         CIMResponseMessage* response = cimRequest->buildResponse();
561         response->cimException = PEGASUS_CIM_EXCEPTION_L(
562             CIM_ERR_FAILED,
563             MessageLoaderParms(
564                 "IndicationService.IndicationService."
565                     "CANNOT_EXECUTE_REQUEST",
566                 "The requested operation cannot be executed."
567                     " IndicationService EnabledState : $0.",
568                 _getEnabledStateString(_enabledState)));
569         _enqueueResponse(cimRequest, response);
570     }
571 }
572
573
574 void IndicationService::handleEnqueue()
575 {
576     Message * message = dequeue();
577
578     PEGASUS_ASSERT(message != 0);
579     handleEnqueue(message);
580 }
581
582 void IndicationService::_initialize()
583 {
584     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "IndicationService::_initialize");
585
586     //
587     //  Find required services
588     _providerManager = find_service_qid(PEGASUS_QUEUENAME_PROVIDERMANAGER_CPP);
589     _handlerService = find_service_qid(PEGASUS_QUEUENAME_INDHANDLERMANAGER);
590
591     //
592     //  Set arrays of valid and supported property values
593     //
594     //  Note: Valid values are defined by the CIM Event Schema MOF
595     //  Supported values are a subset of the valid values
596     //  Some valid values, as defined in the MOF, are not currently supported
597     //  by the Pegasus IndicationService
598     //
599     _validStates.append(STATE_UNKNOWN);
600     _validStates.append(STATE_OTHER);
601     _validStates.append(STATE_ENABLED);
602     _validStates.append(STATE_ENABLEDDEGRADED);
603     _validStates.append(STATE_DISABLED);
604     _supportedStates.append(STATE_ENABLED);
605     _supportedStates.append(STATE_DISABLED);
606     _validRepeatPolicies.append(_POLICY_UNKNOWN);
607     _validRepeatPolicies.append(_POLICY_OTHER);
608     _validRepeatPolicies.append(_POLICY_NONE);
609     _validRepeatPolicies.append(_POLICY_SUPPRESS);
610     _validRepeatPolicies.append(_POLICY_DELAY);
611     _supportedRepeatPolicies.append(_POLICY_UNKNOWN);
612     _supportedRepeatPolicies.append(_POLICY_OTHER);
613     _supportedRepeatPolicies.append(_POLICY_NONE);
614     _supportedRepeatPolicies.append(_POLICY_SUPPRESS);
615     _supportedRepeatPolicies.append(_POLICY_DELAY);
616     _validErrorPolicies.append(_ERRORPOLICY_OTHER);
617     _validErrorPolicies.append(_ERRORPOLICY_IGNORE);
618     _validErrorPolicies.append(_ERRORPOLICY_DISABLE);
619     _validErrorPolicies.append(_ERRORPOLICY_REMOVE);
620     _supportedErrorPolicies.append(_ERRORPOLICY_IGNORE);
621     _supportedErrorPolicies.append(_ERRORPOLICY_DISABLE);
622     _supportedErrorPolicies.append(_ERRORPOLICY_REMOVE);
623     _validPersistenceTypes.append(PERSISTENCE_OTHER);
624     _validPersistenceTypes.append(PERSISTENCE_PERMANENT);
625     _validPersistenceTypes.append(PERSISTENCE_TRANSIENT);
626     _supportedPersistenceTypes.append(PERSISTENCE_PERMANENT);
627     _supportedPersistenceTypes.append(PERSISTENCE_TRANSIENT);
628     _validSNMPVersion.append(SNMPV1_TRAP);
629     _validSNMPVersion.append(SNMPV2C_TRAP);
630     _validSNMPVersion.append(SNMPV2C_INFORM);
631     _validSNMPVersion.append(SNMPV3_TRAP);
632     _validSNMPVersion.append(SNMPV3_INFORM);
633     _supportedSNMPVersion.append(SNMPV1_TRAP);
634     _supportedSNMPVersion.append(SNMPV2C_TRAP);
635
636     //
637     //  Set arrays of names of supported properties for each class
638     //
639     //  Currently, all properties in these classes in CIM 2.5 through CIM 2.9
640     //  final schemas are supported.  If support for a new class is added, a new
641     //  list of names of supported properties for the class must be added as a
642     //  private member to the IndicationService class, and the array values
643     //  must be appended here.  When support for a new property is added, the
644     //  property name must be appended to the appropriate array(s) here.
645     //
646     _supportedSubscriptionProperties.append(PEGASUS_PROPERTYNAME_FILTER);
647     _supportedSubscriptionProperties.append(PEGASUS_PROPERTYNAME_HANDLER);
648     _supportedSubscriptionProperties.append(_PROPERTY_ONFATALERRORPOLICY);
649     _supportedSubscriptionProperties.append(_PROPERTY_OTHERONFATALERRORPOLICY);
650     _supportedSubscriptionProperties.append(
651         _PROPERTY_FAILURETRIGGERTIMEINTERVAL);
652     _supportedSubscriptionProperties.append(
653         PEGASUS_PROPERTYNAME_SUBSCRIPTION_STATE);
654     _supportedSubscriptionProperties.append(_PROPERTY_OTHERSTATE);
655     _supportedSubscriptionProperties.append(_PROPERTY_LASTCHANGE);
656     _supportedSubscriptionProperties.append(_PROPERTY_DURATION);
657     _supportedSubscriptionProperties.append(_PROPERTY_STARTTIME);
658     _supportedSubscriptionProperties.append(_PROPERTY_TIMEREMAINING);
659     _supportedSubscriptionProperties.append(_PROPERTY_REPEATNOTIFICATIONPOLICY);
660     _supportedSubscriptionProperties.append(
661         _PROPERTY_OTHERREPEATNOTIFICATIONPOLICY);
662     _supportedSubscriptionProperties.append(
663         _PROPERTY_REPEATNOTIFICATIONINTERVAL);
664     _supportedSubscriptionProperties.append(_PROPERTY_REPEATNOTIFICATIONGAP);
665     _supportedSubscriptionProperties.append(_PROPERTY_REPEATNOTIFICATIONCOUNT);
666
667     _supportedFormattedSubscriptionProperties =
668         _supportedSubscriptionProperties;
669     _supportedFormattedSubscriptionProperties.append(
670         _PROPERTY_TEXTFORMATOWNINGENTITY);
671     _supportedFormattedSubscriptionProperties.append(
672         _PROPERTY_TEXTFORMATID);
673     _supportedFormattedSubscriptionProperties.append(
674         _PROPERTY_TEXTFORMAT);
675     _supportedFormattedSubscriptionProperties.append(
676         _PROPERTY_TEXTFORMATPARAMETERS);
677
678     _supportedFilterProperties.append(_PROPERTY_CAPTION);
679     _supportedFilterProperties.append(_PROPERTY_DESCRIPTION);
680     _supportedFilterProperties.append(_PROPERTY_ELEMENTNAME);
681     _supportedFilterProperties.append(_PROPERTY_SYSTEMCREATIONCLASSNAME);
682     _supportedFilterProperties.append(_PROPERTY_SYSTEMNAME);
683     _supportedFilterProperties.append(PEGASUS_PROPERTYNAME_CREATIONCLASSNAME);
684     _supportedFilterProperties.append(PEGASUS_PROPERTYNAME_NAME);
685     _supportedFilterProperties.append(_PROPERTY_SOURCENAMESPACE);
686     _supportedFilterProperties.append(PEGASUS_PROPERTYNAME_QUERY);
687     _supportedFilterProperties.append(PEGASUS_PROPERTYNAME_QUERYLANGUAGE);
688
689     Array<CIMName> commonListenerDestinationProperties;
690     commonListenerDestinationProperties.append(_PROPERTY_CAPTION);
691     commonListenerDestinationProperties.append(_PROPERTY_DESCRIPTION);
692     commonListenerDestinationProperties.append(_PROPERTY_ELEMENTNAME);
693     commonListenerDestinationProperties.append(
694         _PROPERTY_SYSTEMCREATIONCLASSNAME);
695     commonListenerDestinationProperties.append(_PROPERTY_SYSTEMNAME);
696     commonListenerDestinationProperties.append(
697         PEGASUS_PROPERTYNAME_CREATIONCLASSNAME);
698     commonListenerDestinationProperties.append(PEGASUS_PROPERTYNAME_NAME);
699     commonListenerDestinationProperties.append(
700         PEGASUS_PROPERTYNAME_PERSISTENCETYPE);
701     commonListenerDestinationProperties.append(_PROPERTY_OTHERPERSISTENCETYPE);
702
703     _supportedCIMXMLHandlerProperties = commonListenerDestinationProperties;
704     _supportedCIMXMLHandlerProperties.append(_PROPERTY_OWNER);
705     _supportedCIMXMLHandlerProperties.append(
706         PEGASUS_PROPERTYNAME_LSTNRDST_DESTINATION);
707
708     _supportedCIMXMLListenerDestinationProperties =
709         commonListenerDestinationProperties;
710     _supportedCIMXMLListenerDestinationProperties.append(
711         PEGASUS_PROPERTYNAME_LSTNRDST_DESTINATION);
712
713     _supportedSNMPHandlerProperties = commonListenerDestinationProperties;
714     _supportedSNMPHandlerProperties.append(_PROPERTY_OWNER);
715     _supportedSNMPHandlerProperties.append(
716         PEGASUS_PROPERTYNAME_LSTNRDST_TARGETHOST);
717     _supportedSNMPHandlerProperties.append(_PROPERTY_TARGETHOSTFORMAT);
718     _supportedSNMPHandlerProperties.append(_PROPERTY_OTHERTARGETHOSTFORMAT);
719     _supportedSNMPHandlerProperties.append(_PROPERTY_PORTNUMBER);
720     _supportedSNMPHandlerProperties.append(PEGASUS_PROPERTYNAME_SNMPVERSION);
721     _supportedSNMPHandlerProperties.append(_PROPERTY_SNMPSECURITYNAME);
722     _supportedSNMPHandlerProperties.append(_PROPERTY_SNMPENGINEID);
723
724     _supportedSyslogListenerDestinationProperties =
725         commonListenerDestinationProperties;
726
727     _supportedEmailListenerDestinationProperties =
728         commonListenerDestinationProperties;
729     _supportedEmailListenerDestinationProperties.append(
730         PEGASUS_PROPERTYNAME_LSTNRDST_MAILTO);
731     _supportedEmailListenerDestinationProperties.append(
732         PEGASUS_PROPERTYNAME_LSTNRDST_MAILCC);
733     _supportedEmailListenerDestinationProperties.append(
734         PEGASUS_PROPERTYNAME_LSTNRDST_MAILSUBJECT);
735
736     ConfigManager* configManager = ConfigManager::getInstance();
737
738     if (ConfigManager::parseBooleanValue(
739         configManager->getCurrentValue("enableIndicationService")))
740     {
741         _enabledState = _ENABLEDSTATE_ENABLED;
742         _initializeActiveSubscriptionsFromRepository(0);
743     }
744
745     PEG_METHOD_EXIT();
746 }
747
748
749
750 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
751
752 String _getReturnCodeString(Uint32 code)
753 {
754     // Method return codes
755     switch(code)
756     {
757         case _RETURNCODE_TIMEOUT:
758             return String("Cannot complete within Timeout Period");
759         case _RETURNCODE_NOTSUPPORTED:
760             return String("Not Supported");
761         case _RETURNCODE_FAILED:
762             return String("Failed");
763         case _RETURNCODE_INVALIDPARAMETER:
764             return String("Invalid Parameter");
765     }
766
767     PEGASUS_ASSERT(false); // Never reach to unknown return code
768
769     return String("Unknown");
770 }
771
772 void IndicationService::_sendIndicationServiceDisabled()
773 {
774     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
775         "IndicationService::_sendIndicationServiceDisabled");
776
777     if (_enabledState == _ENABLEDSTATE_ENABLED)
778     {
779         PEG_METHOD_EXIT();
780         return;
781     }
782
783     CIMIndicationServiceDisabledRequestMessage * request =
784         new CIMIndicationServiceDisabledRequestMessage(
785             XmlWriter::getNextMessageId(),
786             QueueIdStack(_providerManager, getQueueId()));
787
788     AsyncLegacyOperationStart * asyncRequest =
789         new AsyncLegacyOperationStart(
790             0,
791             _providerManager,
792             request);
793     AutoPtr<AsyncReply> asyncReply(SendWait(asyncRequest));
794
795     delete asyncRequest;
796
797     PEG_METHOD_EXIT();
798 }
799
800 void IndicationService::_handleInvokeMethodRequest(Message *message)
801 {
802     Uint32 timeoutSeconds = 0;
803
804     CIMInvokeMethodRequestMessage *request =
805         dynamic_cast<CIMInvokeMethodRequestMessage*>(message);
806
807     PEGASUS_ASSERT(request);
808
809     CIMInvokeMethodResponseMessage *response =
810         static_cast<CIMInvokeMethodResponseMessage*>(request->buildResponse());
811
812     // Get userName and only privileged user can execute this operation
813     String userName = ((IdentityContainer)request->operationContext.get(
814         IdentityContainer::NAME)).getUserName();
815
816 #ifndef PEGASUS_OS_ZOS
817     if (userName.size() && !System::isPrivilegedUser(userName))
818     {
819         throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_ACCESS_DENIED,
820             MessageLoaderParms(
821                 "IndicationService.IndicationService."
822                     "_MSG_NON_PRIVILEGED_ACCESS_DISABLED",
823                 "User ($0) is not authorized to perform this operation.",
824                 userName));
825     }
826 #endif
827
828     CIMException cimException;
829
830     CIMNamespaceName nameSpace = request->nameSpace;
831     CIMName className = request->instanceName.getClassName().getString();
832
833     Uint32 retCode = _RETURNCODE_COMPLETEDWITHNOERROR;
834     Uint16 requestedState;
835
836     if(!nameSpace.equal(PEGASUS_NAMESPACENAME_INTEROP))
837     {
838         cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED,
839             nameSpace.getString());
840     }
841     else if(!className.equal(PEGASUS_CLASSNAME_CIM_INDICATIONSERVICE))
842     {
843         cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED,
844             className.getString());
845     }
846     else if (!request->methodName.equal(_METHOD_REQUESTSTATECHANGE))
847     {
848         cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_METHOD_NOT_FOUND,
849             String::EMPTY);
850     }
851     else
852     {
853         CIMValue cimValue;
854
855         for (Uint32 i = 0, n = request->inParameters.size(); i < n ; ++i)
856         {
857             CIMName name = request->inParameters[i].getParameterName();
858             if (name.equal(_PARAM_REQUESTEDSTATE))
859             {
860                 CIMValue cimValue = request->inParameters[i].getValue();
861                 cimValue.get(requestedState);
862             }
863             else if ((name.equal(_PARAM_TIMEOUTPERIOD)))
864             {
865                 CIMDateTime timeoutInterval;
866                 CIMValue cimValue = request->inParameters[i].getValue();
867                 cimValue.get(timeoutInterval);
868                 if (!timeoutInterval.isInterval())
869                 {
870                     retCode = _RETURNCODE_INVALIDPARAMETER;
871                     break;
872                 }
873                 // Get timeout in seconds
874                 timeoutSeconds =
875                     timeoutInterval.toMicroSeconds() / 1000000;
876             }
877             else
878             {
879                 retCode = _RETURNCODE_INVALIDPARAMETER;
880                 break;
881             }
882         }
883     }
884
885     if (cimException.getCode() == CIM_ERR_SUCCESS &&
886         retCode == _RETURNCODE_COMPLETEDWITHNOERROR)
887     {
888         if (requestedState == _ENABLEDSTATE_ENABLED)
889         {
890             retCode = _enableIndicationService(timeoutSeconds);
891         }
892         else if (requestedState == _ENABLEDSTATE_DISABLED)
893         {
894             retCode = _disableIndicationService(
895                 timeoutSeconds,
896                 cimException);
897         }
898         else
899         {
900             // We don't support any other state changes now.
901             retCode = _RETURNCODE_NOTSUPPORTED;
902         }
903     }
904
905     response->cimException = cimException;
906     response->retValue = CIMValue(retCode);
907     _enqueueResponse(request, response);
908 }
909
910
911 Uint32 IndicationService::_enableIndicationService(Uint32 timeoutSeconds)
912 {
913     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
914         "IndicationService::_enableIndicationService");
915
916     Uint32 retCode = _RETURNCODE_COMPLETEDWITHNOERROR;
917
918     AutoMutex mtx(_mutex);
919
920     // Check if the service is already enabled.
921     if (_enabledState == _ENABLEDSTATE_ENABLED)
922     {
923         // Check if the service is in degraded state.
924         if (_healthState == _HEALTHSTATE_DEGRADEDWARNING)
925         {
926             struct timeval startTime;
927             Time::gettimeofday(&startTime);
928
929             // Wait if there are any pending requests.
930             if (!_waitForAsyncRequestsComplete(&startTime, timeoutSeconds))
931             {
932                 Logger::put(
933                     Logger::STANDARD_LOG,
934                     System::CIMSERVER,
935                     Logger::WARNING,
936                     "Failed to recover from degraded state within timeout "
937                         "period of $0 seconds. There are $1 async"
938                             " requests pending.",
939                     timeoutSeconds,
940                     _asyncRequestsPending.get());
941
942                 retCode = _RETURNCODE_TIMEOUT;
943             }
944             else
945             {
946                 // No async requests pending.
947                 _healthState = _HEALTHSTATE_OK;
948             }
949         }
950         PEG_METHOD_EXIT();
951         return retCode;
952     }
953
954     _enabledState = _ENABLEDSTATE_STARTING;
955
956     String exceptionMsg;
957
958     try
959     {
960         if (_initializeActiveSubscriptionsFromRepository(
961             timeoutSeconds))
962         {
963             _healthState = _HEALTHSTATE_OK;
964         }
965         else
966         {
967             _healthState = _HEALTHSTATE_DEGRADEDWARNING;
968             retCode = _RETURNCODE_TIMEOUT;
969         }
970     }
971     catch (const Exception &e)
972     {
973         exceptionMsg = e.getMessage();
974     }
975     catch (...)
976     {
977         exceptionMsg = "Unknown error";
978     }
979
980     _enabledState = _ENABLEDSTATE_ENABLED;
981     sendSubscriptionInitComplete();
982
983     if (exceptionMsg.size())
984     {
985         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL1,
986             "Exception while enabling the indication Service : %s",
987             (const char*)exceptionMsg.getCString()));
988
989         _healthState = _HEALTHSTATE_DEGRADEDWARNING;
990     }
991
992     PEG_METHOD_EXIT();
993     return retCode;
994 }
995
996 Uint32 IndicationService::_disableIndicationService(Uint32 timeoutSeconds,
997     CIMException &cimException)
998 {
999     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
1000         "IndicationService::_disableIndicationService");
1001
1002     Uint32 retCode = _RETURNCODE_COMPLETEDWITHNOERROR;
1003
1004     AutoMutex mtx(_mutex);
1005
1006     // Check if the service is already disabled.
1007     if (_enabledState == _ENABLEDSTATE_DISABLED)
1008     {
1009         PEG_METHOD_EXIT();
1010         return retCode;
1011     }
1012
1013     _enabledState = _ENABLEDSTATE_SHUTTINGDOWN;
1014
1015     // Wait for threads running other than indication threads.
1016     while (_threads.get() - _processIndicationThreads.get() > 1)
1017     {
1018         Threads::sleep(100);
1019     }
1020
1021     String exceptionMsg;
1022
1023     try
1024     {
1025         if (_deleteActiveSubscriptions(timeoutSeconds))
1026         {
1027             _sendIndicationServiceDisabled();
1028             _enabledState = _ENABLEDSTATE_DISABLED;
1029             _healthState = _HEALTHSTATE_OK;
1030         }
1031         else
1032         {
1033             _enabledState = _ENABLEDSTATE_ENABLED;
1034             retCode = _RETURNCODE_TIMEOUT;
1035             _healthState = _HEALTHSTATE_DEGRADEDWARNING;
1036             cimException = PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1037                 MessageLoaderParms(
1038                     _MSG_STATE_CHANGE_FAILED_KEY,
1039                     _MSG_STATE_CHANGE_FAILED,
1040                     _getReturnCodeString(_RETURNCODE_TIMEOUT),
1041                     _getEnabledStateString(_enabledState),
1042                     _getHealthStateString(_healthState)));
1043         }
1044     }
1045     catch (const Exception &e)
1046     {
1047         exceptionMsg = e.getMessage();
1048     }
1049     catch (...)
1050     {
1051         exceptionMsg = "Unknown Error";
1052     }
1053
1054     if (exceptionMsg.size())
1055     {
1056         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL1,
1057             "Exception while disabling the indication Service : %s",
1058             (const char*)exceptionMsg.getCString()));
1059
1060         _enabledState = _ENABLEDSTATE_ENABLED;
1061         retCode = _RETURNCODE_FAILED;
1062         _healthState = _HEALTHSTATE_DEGRADEDWARNING;
1063         cimException = PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
1064             MessageLoaderParms(
1065                 _MSG_STATE_CHANGE_FAILED_KEY,
1066                 _MSG_STATE_CHANGE_FAILED,
1067                 exceptionMsg,
1068                 _getEnabledStateString(_enabledState),
1069                 _getHealthStateString(_healthState)));
1070     }
1071     PEG_METHOD_EXIT();
1072
1073     return retCode;
1074 }
1075
1076 Boolean IndicationService::_deleteActiveSubscriptions(Uint32 timeoutSeconds)
1077 {
1078     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
1079         "IndicationService::_deleteActiveSubscriptions");
1080
1081     struct timeval startTime;
1082     Time::gettimeofday(&startTime);
1083     Boolean completed = true;
1084
1085     // Check if there are existing pending async requests
1086     if (!_waitForAsyncRequestsComplete(&startTime, timeoutSeconds))
1087     {
1088         Logger::put(
1089             Logger::STANDARD_LOG,
1090             System::CIMSERVER,
1091             Logger::WARNING,
1092             "Failed to disable Indication service within timeout "
1093                 "period of $0 seconds. There are $1 existing async "
1094                     "requests pending.",
1095             timeoutSeconds,
1096             _asyncRequestsPending.get());
1097
1098         PEG_METHOD_EXIT();
1099         return false;
1100     }
1101
1102     Array <ActiveSubscriptionsTableEntry> subscriptionsEntries;
1103     subscriptionsEntries =
1104         _subscriptionTable->getAllActiveSubscriptionEntries();
1105
1106     CIMPropertyList requiredProperties;
1107     String condition;
1108     String query;
1109     String queryLanguage;
1110
1111     for (Uint32 i=0; i < subscriptionsEntries.size(); i++)
1112     {
1113         CIMInstance instance = subscriptionsEntries[i].subscription;
1114         String creator = instance.getProperty (instance.findProperty
1115             (PEGASUS_PROPERTYNAME_INDSUB_CREATOR)).getValue ().toString ();
1116
1117         AcceptLanguageList acceptLangs;
1118         Uint32 propIndex = instance.findProperty(
1119             PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS);
1120         if (propIndex != PEG_NOT_FOUND)
1121         {
1122             String acceptLangsString;
1123             instance.getProperty(propIndex).getValue().get(acceptLangsString);
1124             if (acceptLangsString.size())
1125             {
1126                 acceptLangs = LanguageParser::parseAcceptLanguageHeader(
1127                     acceptLangsString);
1128             }
1129         }
1130         ContentLanguageList contentLangs;
1131         propIndex = instance.findProperty
1132             (PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS);
1133         if (propIndex != PEG_NOT_FOUND)
1134         {
1135             String contentLangsString;
1136             instance.getProperty(propIndex).getValue().get(
1137                 contentLangsString);
1138             if (contentLangsString.size())
1139             {
1140                 contentLangs = LanguageParser::parseContentLanguageHeader(
1141                     contentLangsString);
1142             }
1143         }
1144         CIMNamespaceName sourceNameSpace;
1145         Array<CIMName> indicationSubclasses;
1146
1147         _getCreateParams (instance,
1148             indicationSubclasses, requiredProperties,
1149             sourceNameSpace, condition, query, queryLanguage);
1150
1151         _sendAsyncDeleteRequests(
1152             subscriptionsEntries[i].providers,
1153             sourceNameSpace,
1154             instance,
1155             acceptLangs,
1156             contentLangs,
1157             0,  // no request
1158             indicationSubclasses,
1159             creator);
1160
1161     }
1162
1163     if (!_waitForAsyncRequestsComplete(&startTime, timeoutSeconds))
1164     {
1165         Logger::put(
1166             Logger::STANDARD_LOG,
1167             System::CIMSERVER,
1168             Logger::WARNING,
1169             "Failed to disable Indication service within timeout "
1170                 "period of $0 seconds. There are $1 async requests pending.",
1171             timeoutSeconds,
1172             _asyncRequestsPending.get());
1173
1174         completed = false;
1175     }
1176     else
1177     {
1178 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
1179         _providerIndicationCountTable.clear();
1180 #endif
1181
1182         _subscriptionTable->clear();
1183     }
1184
1185     PEG_METHOD_EXIT();
1186
1187     return completed;
1188 }
1189
1190
1191 Boolean IndicationService::_waitForAsyncRequestsComplete(
1192     struct timeval* startTime,
1193     Uint32 timeoutSeconds)
1194 {
1195     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
1196         "IndicationService::_waitForAsyncRequestsComplete");
1197
1198     struct timeval timeNow;
1199     Boolean requestsPending = false;
1200     while (_asyncRequestsPending.get() > 0)
1201     {
1202         if (timeoutSeconds)
1203         {
1204             Time::gettimeofday(&timeNow);
1205             if ((Uint32)(timeNow.tv_sec - startTime->tv_sec) > timeoutSeconds)
1206             {
1207                 requestsPending = true;
1208                 break;
1209             }
1210         }
1211         Threads::sleep(100);
1212     }
1213     PEG_METHOD_EXIT();
1214
1215     return !requestsPending;
1216 }
1217
1218 void IndicationService::_sendSubscriptionNotActiveMessagetoHandlerService(
1219         const CIMObjectPath &subscriptionName)
1220 {
1221     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
1222         "IndicationService::_sendSubscriptionNotActiveMessagetoHandlerService");
1223
1224        CIMRequestMessage * notifyRequest =
1225         new CIMNotifySubscriptionNotActiveRequestMessage (
1226             XmlWriter::getNextMessageId (),
1227             subscriptionName,
1228             QueueIdStack(_handlerService));
1229
1230     AsyncLegacyOperationStart *req =
1231         new AsyncLegacyOperationStart(
1232         0,
1233         _handlerService,
1234         notifyRequest);
1235
1236     AsyncReply *reply = SendWait(req);
1237     delete req;
1238     delete reply;
1239
1240     PEG_METHOD_EXIT();
1241 }
1242
1243 void IndicationService::_sendListenerNotActiveMessagetoHandlerService(
1244         const CIMObjectPath &handlerName)
1245 {
1246     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
1247         "IndicationService::_sendListenerNotActiveMessagetoHandlerService");
1248
1249     // Send notify request only to CIMXML handlers
1250     {
1251         CIMRequestMessage * notifyRequest =
1252             new CIMNotifyListenerNotActiveRequestMessage (
1253                 XmlWriter::getNextMessageId (),
1254                 handlerName,
1255                 QueueIdStack(_handlerService));
1256
1257          AsyncLegacyOperationStart *req =
1258              new AsyncLegacyOperationStart(
1259              0,
1260              _handlerService,
1261              notifyRequest);
1262
1263          AsyncReply *reply = SendWait(req);
1264          delete req;
1265          delete reply;
1266     }
1267
1268     PEG_METHOD_EXIT();
1269 }
1270
1271 #endif
1272
1273 void IndicationService::_updateAcceptedSubscription(
1274     CIMInstance &subscription,
1275     const Array<ProviderClassList> &acceptedProviders,
1276     const Array<CIMName> &indicationSubclasses,
1277     const CIMNamespaceName &sourceNameSpace)
1278 {
1279     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
1280         "IndicationService::_updateAcceptedSubscription");
1281
1282     if (acceptedProviders.size() == 0)
1283     {
1284         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL2,
1285             "No providers accepted subscription on initialization: %s",
1286             (const char *)
1287                 subscription.getPath().toString().getCString()));
1288
1289         //
1290         //  No providers accepted the subscription
1291         //  Implement the subscription's On Fatal Error Policy
1292         //  If subscription is not disabled or removed, send alert and
1293         //  Insert entries into the subscription hash tables
1294         //
1295         if (!_subscriptionRepository->reconcileFatalError(
1296             subscription))
1297         {
1298             //
1299             //  Insert entries into the subscription hash tables
1300             //
1301             _subscriptionTable->insertSubscription(
1302                 subscription,
1303                 acceptedProviders,
1304                 indicationSubclasses,
1305                 sourceNameSpace);
1306
1307 #if 0
1308             //
1309             //  Send alert
1310             //
1311             //
1312             //  Send NoProviderAlertIndication to handler instances
1313             //  ATTN: NoProviderAlertIndication must be defined
1314             //
1315             Array<CIMInstance> subscriptions;
1316             subscriptions.append(activeSubscriptions[i]);
1317             CIMInstance indicationInstance = _createAlertInstance(
1318                 _CLASS_NO_PROVIDER_ALERT, subscriptions);
1319
1320             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
1321                 "Sending NoProvider Alert for %u subscriptions",
1322                  subscriptions.size()));
1323             _sendAlerts(subscriptions, indicationInstance);
1324 #endif
1325
1326             //
1327             //  Get Subscription Filter Name and Handler Name
1328             //
1329             String logString = _getSubscriptionLogString(
1330                 subscription);
1331
1332             //
1333             //  Log a message for the subscription
1334             //
1335             Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
1336                 Logger::WARNING,
1337                 MessageLoaderParms(
1338                     _MSG_NO_PROVIDER_KEY,
1339                     _MSG_NO_PROVIDER,
1340                     logString,
1341                     subscription.getPath().getNameSpace().getString()));
1342         }
1343     }
1344     else
1345     {
1346         //
1347         //  At least one provider accepted the subscription
1348         //  Insert entries into the subscription hash tables
1349         //
1350         _subscriptionTable->insertSubscription(
1351             subscription,
1352             acceptedProviders,
1353             indicationSubclasses,
1354             sourceNameSpace);
1355     }
1356
1357     PEG_METHOD_EXIT();
1358 }
1359
1360 Boolean IndicationService::_initializeActiveSubscriptionsFromRepository(
1361     Uint32 timeoutSeconds)
1362 {
1363     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
1364         "IndicationService::_initializeActiveSubscriptionsFromRepository");
1365
1366     struct timeval startTime;
1367     Time::gettimeofday(&startTime);
1368     Boolean completed = true;
1369
1370 #ifdef PEGASUS_INDICATION_PERFINST
1371     Stopwatch stopWatch;
1372
1373     stopWatch.start();
1374 #endif
1375
1376     //  Create Subscription Repository
1377     _subscriptionRepository.reset(new SubscriptionRepository(_cimRepository));
1378
1379 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
1380     _asyncRequestsPending = 0;
1381     _processIndicationThreads = 0;
1382 #endif
1383
1384    //  Create Subscription Table
1385    _subscriptionTable.reset(
1386        new SubscriptionTable(_subscriptionRepository.get()));
1387
1388 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
1389     _providerIndicationCountTable.clear();
1390 #endif
1391
1392     Array<CIMInstance> activeSubscriptions;
1393     Array<CIMInstance> noProviderSubscriptions;
1394     Boolean invalidInstance = false;
1395     //
1396     //  Get existing active subscriptions from each namespace in the repository
1397     //
1398     invalidInstance = _subscriptionRepository->getActiveSubscriptions(
1399         activeSubscriptions);
1400     noProviderSubscriptions.clear();
1401
1402     PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
1403         "%u active subscription(s) found on initialization",
1404         activeSubscriptions.size()));
1405
1406     String condition;
1407     String query;
1408     String queryLanguage;
1409     CIMPropertyList propertyList;
1410     Array<ProviderClassList> indicationProviders;
1411
1412     for (Uint32 i = 0; i < activeSubscriptions.size(); i++)
1413     {
1414         //
1415         //  Check for expired subscription
1416         //
1417         try
1418         {
1419             if (_isExpired(activeSubscriptions[i]))
1420             {
1421                 CIMObjectPath path = activeSubscriptions[i].getPath();
1422
1423                 PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
1424                     "Deleting expired subscription on initialization: %s",
1425                     (const char *) path.toString().getCString()));
1426
1427                 _deleteExpiredSubscription(path);
1428
1429 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
1430                 _sendSubscriptionNotActiveMessagetoHandlerService(path);
1431 #endif
1432                 // If subscription is expired delete the subscription
1433                 // and continue on to the next one.
1434                 continue;
1435             }
1436         }
1437         catch (DateTimeOutOfRangeException& e)
1438         {
1439             //
1440             //  This instance from the repository is invalid
1441             //  Log a message and skip it
1442             //
1443             Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
1444                 Logger::WARNING,
1445                 MessageLoaderParms(
1446                     "IndicationService.IndicationService."
1447                         "INVALID_SUBSCRIPTION_INSTANCE_IGNORED",
1448                     "An invalid Subscription instance was ignored: $0.",
1449                     e.getMessage()));
1450             continue;
1451         }
1452
1453         CIMNamespaceName sourceNameSpace;
1454         Array<CIMName> indicationSubclasses;
1455         _getCreateParams(activeSubscriptions[i], indicationSubclasses,
1456             indicationProviders, propertyList, sourceNameSpace, condition,
1457             query, queryLanguage);
1458
1459         if (indicationProviders.size() == 0)
1460         {
1461             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL2,
1462                 "No providers found for subscription on initialization: %s",
1463                 (const char *)
1464                     activeSubscriptions[i].getPath().toString().getCString()));
1465
1466             //
1467             //  There are no providers that can support this subscription
1468             //  Implement the subscription's On Fatal Error Policy
1469             //  If subscription is not disabled or removed,
1470             //  Append this subscription to no provider list and
1471             //  Insert entries into the subscription hash tables
1472             //
1473             if (!_subscriptionRepository->reconcileFatalError(
1474                     activeSubscriptions[i]))
1475             {
1476                 noProviderSubscriptions.append(activeSubscriptions[i]);
1477
1478                 _subscriptionTable->insertSubscription(activeSubscriptions[i],
1479                     indicationProviders, indicationSubclasses, sourceNameSpace);
1480             }
1481             continue;
1482         }
1483
1484         //
1485         //  Send Create request message to each provider
1486         //  NOTE: These Create requests are not associated with a user request,
1487         //  so there is no associated authType or userName
1488         //  The Creator from the subscription instance is used for userName,
1489         //  and authType is not set
1490         //
1491         CIMInstance instance = activeSubscriptions[i];
1492         String creator;
1493         if (!_getCreator(instance, creator))
1494         {
1495             //
1496             //  This instance from the repository is corrupted
1497             //  Skip it
1498             //
1499             invalidInstance = true;
1500             continue;
1501         }
1502
1503         // Get the language tags that were saved with the subscription instance
1504         AcceptLanguageList acceptLangs;
1505         Uint32 propIndex = instance.findProperty(
1506             PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS);
1507         if (propIndex != PEG_NOT_FOUND)
1508         {
1509             String acceptLangsString;
1510             instance.getProperty(propIndex).getValue().get(acceptLangsString);
1511             if (acceptLangsString.size())
1512             {
1513                 acceptLangs = LanguageParser::parseAcceptLanguageHeader(
1514                     acceptLangsString);
1515             }
1516         }
1517         ContentLanguageList contentLangs;
1518         propIndex = instance.findProperty(
1519             PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS);
1520         if (propIndex != PEG_NOT_FOUND)
1521         {
1522             String contentLangsString;
1523             instance.getProperty(propIndex).getValue().get(contentLangsString);
1524             if (contentLangsString.size())
1525             {
1526                 contentLangs = LanguageParser::parseContentLanguageHeader(
1527                     contentLangsString);
1528             }
1529         }
1530
1531         // If Indication profile support is enabled indication service can be
1532         // enabled dynamically. Send create subscription requests using
1533         // SendAsync() to honor the timeout.
1534 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
1535         if (timeoutSeconds > 0) // if timeout is specified
1536         {
1537             _sendAsyncCreateRequests(
1538                 indicationProviders,
1539                 sourceNameSpace,
1540                 propertyList,
1541                 condition,
1542                 query,
1543                 queryLanguage,
1544                 activeSubscriptions[i],
1545                 acceptLangs,
1546                 contentLangs,
1547                 0, // original request is 0
1548                 indicationSubclasses,
1549                 creator);
1550         }
1551         else
1552 #endif
1553         //
1554         //  Send Create request message to each provider using SendWait() if
1555         //  timeout is not specified.
1556         //  Note: SendWait is used instead of SendAsync.  Initialization must
1557         //  deal with multiple subscriptions, each with multiple providers.
1558         //  Using SendWait eliminates the need for a callback and the necessity
1559         //  to handle multiple levels of aggregation, which would add
1560         //  significant complexity.  Since initialization cannot complete
1561         //  anyway until responses have been received for all subscriptions,
1562         //  from all the providers, use of SendWait should not cause a
1563         //  significant performance issue.
1564         //
1565         {
1566             Array<ProviderClassList> acceptedProviders;
1567             acceptedProviders = _sendWaitCreateRequests(
1568                 indicationProviders,
1569                 sourceNameSpace,
1570                 propertyList,
1571                 condition,
1572                 query,
1573                 queryLanguage,
1574                 activeSubscriptions[i],
1575                 acceptLangs,
1576                 contentLangs,
1577                 creator);
1578
1579             _updateAcceptedSubscription(
1580                 activeSubscriptions[i],
1581                 acceptedProviders,
1582                 indicationSubclasses,
1583                 sourceNameSpace);
1584         }
1585     }  // for each active subscription
1586
1587
1588 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
1589         if (timeoutSeconds > 0)
1590         {
1591             if (!_waitForAsyncRequestsComplete(&startTime, timeoutSeconds))
1592             {
1593                 Logger::put(
1594                     Logger::STANDARD_LOG,
1595                     System::CIMSERVER,
1596                     Logger::WARNING,
1597                     "Failed to enable Indication service within timeout "
1598                         "period of $0 seconds. There are $1 async"
1599                             " requests pending.",
1600                     timeoutSeconds,
1601                     _asyncRequestsPending.get());
1602                 completed = false;
1603             }
1604         }
1605 #endif
1606
1607     //
1608     //  Log a message if any invalid instances were found
1609     //
1610     if (invalidInstance)
1611     {
1612         Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
1613             MessageLoaderParms(
1614                 _MSG_INVALID_INSTANCES_KEY, _MSG_INVALID_INSTANCES));
1615     }
1616     //
1617     //  Log a message for any subscription for which there is no longer any
1618     //  provider
1619     //
1620     if (noProviderSubscriptions.size() > 0)
1621     {
1622 #if 0
1623         //
1624         //  Send NoProviderAlertIndication to handler instances
1625         //  ATTN: NoProviderAlertIndication must be defined
1626         //
1627         CIMInstance indicationInstance = _createAlertInstance(
1628             _CLASS_NO_PROVIDER_ALERT, noProviderSubscriptions);
1629
1630         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
1631             "Sending NoProvider Alert for %u subscriptions",
1632             noProviderSubscriptions.size()));
1633         _sendAlerts(noProviderSubscriptions, indicationInstance);
1634 #endif
1635         //
1636         //  Log a message for each subscription
1637         //
1638         for (Uint32 i = 0; i < noProviderSubscriptions.size(); i++)
1639         {
1640             //
1641             //  Get Subscription Filter Name and Handler Name
1642             //
1643             String logString =
1644                 _getSubscriptionLogString(noProviderSubscriptions[i]);
1645
1646             Logger::put_l(
1647                 Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
1648                 MessageLoaderParms(
1649                     _MSG_NO_PROVIDER_KEY,
1650                     _MSG_NO_PROVIDER,
1651                     logString,
1652                     noProviderSubscriptions[i].getPath().getNameSpace().
1653                         getString()));
1654         }
1655     }
1656
1657 #ifdef PEGASUS_INDICATION_PERFINST
1658     stopWatch.stop();
1659
1660     PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
1661         "%s: %.3f seconds", "Initialize", stopWatch.getElapsed()));
1662 #endif
1663
1664     PEG_METHOD_EXIT();
1665
1666     return completed;
1667 }
1668
1669 void IndicationService::_terminate()
1670 {
1671     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "IndicationService::_terminate");
1672
1673     Array<CIMInstance> activeSubscriptions;
1674     CIMInstance indicationInstance;
1675
1676     //
1677     //  A message is already logged that CIM Server is shutting down --
1678     //  no need to log a message
1679     //
1680 #if 0
1681     //
1682     //  Get existing active subscriptions from hash table
1683     //
1684     activeSubscriptions = _getActiveSubscriptions();
1685
1686     if (activeSubscriptions.size() > 0)
1687     {
1688         //
1689         //  Create CimomShutdownAlertIndication instance
1690         //  ATTN: CimomShutdownAlertIndication must be defined
1691         //
1692         indicationInstance = _createAlertInstance(
1693             _CLASS_CIMOM_SHUTDOWN_ALERT, activeSubscriptions);
1694
1695         //
1696         //  Send CimomShutdownAlertIndication to each unique handler instance
1697         //
1698         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
1699             "Sending CIMServerShutdown Alert for %u subscriptions",
1700             activeSubscriptions.size()));
1701         _sendAlerts(activeSubscriptions, indicationInstance);
1702     }
1703 #endif
1704
1705     //
1706     //  Remove entries from the SubscriptionTable's Active Subscriptions and
1707     //  Subscription Classes tables
1708     //
1709     //  NOTE: The table entries are removed when the SubscriptionTable
1710     //  destructor is called by the IndicationService destructor.  However,
1711     //  currently the IndicationService destructor is never called, so the
1712     //  IndicationService must call the SubscriptionTable clear() function to
1713     //  remove the table entries.
1714     _subscriptionTable->clear();
1715
1716     PEG_METHOD_EXIT();
1717 }
1718
1719 void IndicationService::_checkNonprivilegedAuthorization(
1720     const String& userName)
1721 {
1722 #ifndef PEGASUS_OS_ZOS
1723     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
1724         "IndicationService::_checkNonprivilegedAuthorization");
1725
1726     if (!_enableSubscriptionsForNonprivilegedUsers)
1727     {
1728         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
1729             "_checkNonprivilegedAuthorization - checking whether user %s is "
1730                 "privileged",
1731             (const char*) userName.getCString()));
1732         if (!System::isPrivilegedUser(userName))
1733         {
1734             MessageLoaderParms parms(
1735                 "IndicationService.IndicationService."
1736                     "_MSG_NON_PRIVILEGED_ACCESS_DISABLED",
1737                 "User ($0) is not authorized to perform this operation.",
1738                 userName);
1739             PEG_METHOD_EXIT();
1740             throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_ACCESS_DENIED, parms);
1741         }
1742     }
1743
1744     PEG_METHOD_EXIT();
1745 #endif
1746 }
1747
1748 void IndicationService::_handleCreateInstanceRequest(const Message * message)
1749 {
1750     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
1751         "IndicationService::_handleCreateInstanceRequest");
1752
1753     CIMCreateInstanceRequestMessage* request =
1754         (CIMCreateInstanceRequestMessage*) message;
1755
1756     Boolean responseSent = false;
1757
1758     CIMObjectPath instanceRef;
1759     CIMObjectPath subscriptionPath;
1760
1761     CIMInstance instance = request->newInstance.clone();
1762
1763     String userName = ((IdentityContainer)request->operationContext.get(
1764         IdentityContainer::NAME)).getUserName();
1765     _checkNonprivilegedAuthorization(userName);
1766
1767     AcceptLanguageList acceptLangs =
1768         ((AcceptLanguageListContainer)request->operationContext.get(
1769             AcceptLanguageListContainer::NAME)).getLanguages();
1770     ContentLanguageList contentLangs =
1771         ((ContentLanguageListContainer)request->operationContext.get(
1772             ContentLanguageListContainer::NAME)).getLanguages();
1773
1774     if (_canCreate(instance, request->nameSpace))
1775     {
1776         //
1777         //  If the instance is of the PEGASUS_CLASSNAME_INDSUBSCRIPTION
1778         //  class or the PEGASUS_CLASSNAME_FORMATTEDINDSUBSCRIPTION
1779         //  class and subscription state is enabled, determine if any
1780         //  providers can serve the subscription
1781         //
1782         Uint16 subscriptionState;
1783         String condition;
1784         String query;
1785         String queryLanguage;
1786         CIMPropertyList requiredProperties;
1787         CIMNamespaceName sourceNameSpace;
1788         Array<CIMName> indicationSubclasses;
1789         Array<ProviderClassList> indicationProviders;
1790
1791         if ((instance.getClassName().equal(
1792                  PEGASUS_CLASSNAME_INDSUBSCRIPTION)) ||
1793             (instance.getClassName().equal(
1794                  PEGASUS_CLASSNAME_FORMATTEDINDSUBSCRIPTION)))
1795         {
1796             _subscriptionRepository->
1797                 beginCreateSubscription(instance.getPath());
1798
1799             try
1800             {
1801                 subscriptionPath = instance.getPath();
1802                 //
1803                 //  Get subscription state
1804                 //
1805                 //  NOTE: _canCreate has already validated the
1806                 //  SubscriptionState property in the instance; if missing, it
1807                 //  was added with the default value; if null, it was set to
1808                 //  the default value; if invalid, an exception was thrown
1809                 //
1810                 CIMValue subscriptionStateValue;
1811                 subscriptionStateValue = instance.getProperty(
1812                     instance.findProperty(
1813                         PEGASUS_PROPERTYNAME_SUBSCRIPTION_STATE)).getValue();
1814                 subscriptionStateValue.get(subscriptionState);
1815
1816                 if ((subscriptionState == STATE_ENABLED) ||
1817                     (subscriptionState == STATE_ENABLEDDEGRADED))
1818                 {
1819                     _getCreateParams(instance, indicationSubclasses,
1820                         indicationProviders, requiredProperties,
1821                         sourceNameSpace, condition, query, queryLanguage);
1822
1823                     if (indicationProviders.size() == 0)
1824                     {
1825                         //
1826                         //  There are no providers that can support this
1827                         //  subscription
1828                         //
1829
1830                         throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_NOT_SUPPORTED,
1831                             MessageLoaderParms(_MSG_NO_PROVIDERS_KEY,
1832                                 _MSG_NO_PROVIDERS));
1833                     }
1834
1835                     //
1836                     //  Send Create request message to each provider
1837                     //
1838                     _sendAsyncCreateRequests(indicationProviders,
1839                         sourceNameSpace, requiredProperties, condition,
1840                         query, queryLanguage, instance,
1841                         acceptLangs,
1842                         contentLangs,
1843                         request,
1844                         indicationSubclasses,
1845                         userName, request->authType);
1846
1847                     //
1848                     //  Response is sent from _handleCreateResponseAggregation
1849                     //
1850                     responseSent = true;
1851                 }
1852                 else
1853                 {
1854                     //
1855                     //  Create instance for disabled subscription
1856                     //
1857                     instanceRef = _subscriptionRepository->createInstance(
1858                         instance, request->nameSpace, userName,
1859                         acceptLangs, contentLangs, false);
1860                 }
1861             }
1862             catch (...)
1863             {
1864                 _subscriptionRepository->cancelCreateSubscription(
1865                     subscriptionPath);
1866                 throw;
1867             }
1868         }
1869         else
1870         {
1871             //
1872             //  Create instance for filter or handler
1873             //
1874             instanceRef = _subscriptionRepository->createInstance(
1875                 instance, request->nameSpace, userName,
1876                 acceptLangs, contentLangs, false);
1877         }
1878     }
1879
1880     //
1881     //  Send response, if not sent from callback
1882     //  (for example, if there are no indication providers that can support a
1883     //  subscription)
1884     //
1885     if (!responseSent)
1886     {
1887 // l10n - no Content-Language in response
1888         CIMCreateInstanceResponseMessage* response =
1889             dynamic_cast<CIMCreateInstanceResponseMessage*>(
1890                 request->buildResponse());
1891         PEGASUS_ASSERT(response != 0);
1892         response->instanceName = instanceRef;
1893         _enqueueResponse(request, response);
1894     }
1895
1896     PEG_METHOD_EXIT();
1897 }
1898
1899 void IndicationService::_handleGetInstanceRequest(const Message* message)
1900 {
1901     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
1902         "IndicationService::_handleGetInstanceRequest");
1903
1904     CIMGetInstanceRequestMessage* request =
1905         (CIMGetInstanceRequestMessage*) message;
1906
1907     CIMInstance instance;
1908     String contentLangsString;
1909
1910     String userName = ((IdentityContainer)request->operationContext.
1911         get(IdentityContainer::NAME)).getUserName();
1912
1913 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
1914     if (request->className.equal(PEGASUS_CLASSNAME_CIM_INDICATIONSERVICE)||
1915         request->className.equal(
1916             PEGASUS_CLASSNAME_CIM_INDICATIONSERVICECAPABILITIES))
1917     {
1918         _checkNonprivilegedAuthorization(userName);
1919         instance = _indicationServiceConfiguration->getInstance(
1920             request->nameSpace,
1921             request->instanceName,
1922             request->includeQualifiers,
1923             request->includeClassOrigin,
1924             request->propertyList);
1925     }
1926     else
1927 #endif
1928
1929 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
1930     if (request->className.equal(PEGASUS_CLASSNAME_PROVIDERINDDATA))
1931     {
1932         instance = _providerIndicationCountTable.
1933             getProviderIndicationDataInstance(request->instanceName);
1934     }
1935     else if (request->className.equal(
1936              PEGASUS_CLASSNAME_SUBSCRIPTIONINDDATA))
1937     {
1938         instance = _subscriptionTable->
1939             getSubscriptionIndicationDataInstance(request->instanceName);
1940     }
1941     else
1942 #endif
1943     {
1944         _checkNonprivilegedAuthorization(userName);
1945
1946         //
1947         //  Add Creator to property list, if not null
1948         //  Also, if a Subscription and Time Remaining is requested,
1949         //  Ensure Subscription Duration and Start Time are in property list
1950         //
1951         Boolean setTimeRemaining;
1952         Boolean startTimeAdded;
1953         Boolean durationAdded;
1954         CIMPropertyList propertyList = request->propertyList;
1955         CIMName className = request->instanceName.getClassName();
1956         _updatePropertyList(
1957             className,
1958             propertyList,
1959             setTimeRemaining,
1960             startTimeAdded,
1961             durationAdded);
1962
1963         //
1964         //  Get instance from repository
1965         //
1966         instance = _subscriptionRepository->getInstance(
1967             request->nameSpace,
1968             request->instanceName,
1969             request->includeQualifiers,
1970             request->includeClassOrigin,
1971             propertyList);
1972
1973         //
1974         //  Remove Creator property from instance before returning
1975         //
1976         String creator;
1977         if (!_getCreator(instance, creator))
1978         {
1979             //
1980             //  This instance from the repository is corrupted
1981             //
1982             MessageLoaderParms parms(
1983                 _MSG_INVALID_INSTANCES_KEY,
1984                 _MSG_INVALID_INSTANCES);
1985             throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, parms);
1986         }
1987         instance.removeProperty(
1988             instance.findProperty(
1989                 PEGASUS_PROPERTYNAME_INDSUB_CREATOR));
1990
1991         // Remove CretaionTime property from CIMXML handlers
1992         CIMName clsName = instance.getClassName();
1993
1994         if (clsName.equal(PEGASUS_CLASSNAME_INDHANDLER_CIMXML) ||
1995             clsName.equal(PEGASUS_CLASSNAME_LSTNRDST_CIMXML))
1996         {
1997             Uint32 idx = instance.findProperty(
1998                 PEGASUS_PROPERTYNAME_LSTNRDST_CREATIONTIME);
1999
2000             if (idx  != PEG_NOT_FOUND)
2001             {
2002                 instance.removeProperty(idx);
2003             }
2004         }
2005
2006
2007         //
2008         //  Remove the language properties from instance before returning
2009         //
2010         Uint32 propIndex = instance.findProperty(
2011             PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS);
2012         if (propIndex != PEG_NOT_FOUND)
2013         {
2014             instance.removeProperty(propIndex);
2015         }
2016
2017         propIndex = instance.findProperty(
2018             PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS);
2019         if (propIndex != PEG_NOT_FOUND)
2020         {
2021              // Get the content languages to be sent in the Content-Language
2022              // header
2023              instance.getProperty(propIndex).getValue().
2024                  get(contentLangsString);
2025              instance.removeProperty(propIndex);
2026         }
2027
2028         //
2029         //  If a subscription with a duration, calculate subscription time
2030         //  remaining, and add property to the instance
2031         //
2032         if (setTimeRemaining)
2033         {
2034             _setTimeRemaining(instance);
2035             if (startTimeAdded)
2036             {
2037                 instance.removeProperty(
2038                     instance.findProperty(
2039                         _PROPERTY_STARTTIME));
2040             }
2041             if (durationAdded)
2042             {
2043                 instance.removeProperty(
2044                     instance.findProperty(
2045                         _PROPERTY_DURATION));
2046             }
2047         }
2048     }
2049
2050     CIMGetInstanceResponseMessage * response =
2051         dynamic_cast<CIMGetInstanceResponseMessage *>(request->buildResponse());
2052     if (contentLangsString.size())
2053     {
2054         // Note: setting Content-Language in the response to the
2055         // contentLanguage in the repository.
2056         response->operationContext.set(ContentLanguageListContainer(
2057             LanguageParser::parseContentLanguageHeader(contentLangsString)));
2058     }
2059     response->getResponseData().setInstance(instance);
2060     _enqueueResponse(request, response);
2061
2062     PEG_METHOD_EXIT();
2063 }
2064
2065 void IndicationService::_handleEnumerateInstancesRequest(const Message* message)
2066 {
2067     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
2068         "IndicationService::_handleEnumerateInstancesRequest");
2069
2070     CIMEnumerateInstancesRequestMessage* request =
2071         (CIMEnumerateInstancesRequestMessage*) message;
2072
2073     Array<CIMInstance> returnedInstances;
2074     String aggregatedLangs;
2075
2076     String userName = ((IdentityContainer)request->operationContext.
2077         get(IdentityContainer::NAME)).getUserName();
2078
2079 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
2080     if (request->className.equal(PEGASUS_CLASSNAME_CIM_INDICATIONSERVICE) ||
2081         request->className.equal(
2082             PEGASUS_CLASSNAME_CIM_INDICATIONSERVICECAPABILITIES))
2083     {
2084         _checkNonprivilegedAuthorization(userName);
2085         returnedInstances = _indicationServiceConfiguration->
2086             enumerateInstancesForClass(
2087                 request->nameSpace,
2088                 request->className,
2089                 request->includeQualifiers,
2090                 request->includeClassOrigin,
2091                 request->propertyList);
2092     }
2093     else
2094 #endif
2095
2096 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
2097     if (request->className.equal(PEGASUS_CLASSNAME_PROVIDERINDDATA))
2098     {
2099         returnedInstances = _providerIndicationCountTable.
2100             enumerateProviderIndicationDataInstances();
2101     }
2102     else if (request->className.equal(
2103              PEGASUS_CLASSNAME_SUBSCRIPTIONINDDATA))
2104     {
2105         returnedInstances = _subscriptionTable->
2106             enumerateSubscriptionIndicationDataInstances();
2107     }
2108     else
2109 #endif
2110     {
2111         _checkNonprivilegedAuthorization(userName);
2112         Array<CIMInstance> enumInstances;
2113
2114         //
2115         //  Add Creator to property list, if not null
2116         //  Also, if a Subscription and Time Remaining is requested,
2117         //  Ensure Subscription Duration and Start Time are in property
2118         //  list
2119         //
2120         Boolean setTimeRemaining;
2121         Boolean startTimeAdded;
2122         Boolean durationAdded;
2123         CIMPropertyList propertyList = request->propertyList;
2124         _updatePropertyList(request->className,
2125             propertyList, setTimeRemaining, startTimeAdded, durationAdded);
2126
2127         enumInstances =
2128             _subscriptionRepository->enumerateInstancesForClass(
2129                 request->nameSpace, request->className,
2130                 request->includeQualifiers, request->includeClassOrigin,
2131                 propertyList);
2132
2133         // Vars used to aggregate the content languages of the subscription
2134         // instances.
2135         Boolean langMismatch = false;
2136         Uint32 propIndex;
2137
2138         //
2139         //  Remove Creator and language properties from instances before
2140         //  returning
2141         //
2142         for (Uint32 i = 0; i < enumInstances.size(); i++)
2143         {
2144             String creator;
2145             if (!_getCreator(enumInstances[i], creator))
2146             {
2147                 //
2148                 //  This instance from the repository is corrupted
2149                 //  Skip it
2150                 //
2151                 continue;
2152             }
2153
2154             enumInstances[i].removeProperty(
2155                 enumInstances[i].findProperty(
2156                     PEGASUS_PROPERTYNAME_INDSUB_CREATOR));
2157
2158             // Remove CretaionTime property from CIMXML handlers
2159             CIMName clsName = enumInstances[i].getClassName();
2160
2161             if (clsName.equal(PEGASUS_CLASSNAME_INDHANDLER_CIMXML) ||
2162                 clsName.equal(PEGASUS_CLASSNAME_LSTNRDST_CIMXML))
2163             {
2164                 Uint32 idx = enumInstances[i].findProperty(
2165                     PEGASUS_PROPERTYNAME_LSTNRDST_CREATIONTIME);
2166
2167                 if (idx  != PEG_NOT_FOUND)
2168                 {
2169                     enumInstances[i].removeProperty(idx);
2170                 }
2171             }
2172
2173             propIndex = enumInstances[i].findProperty(
2174                 PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS);
2175             String contentLangs;
2176             if (propIndex != PEG_NOT_FOUND)
2177             {
2178                 enumInstances[i].getProperty(propIndex).getValue().get(
2179                     contentLangs);
2180                 enumInstances[i].removeProperty(propIndex);
2181             }
2182
2183             propIndex = enumInstances[i].findProperty(
2184                 PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS);
2185             if (propIndex != PEG_NOT_FOUND)
2186             {
2187                 enumInstances[i].removeProperty(propIndex);
2188             }
2189
2190             // Determine what to set into the Content-Language header back
2191             // to the client
2192             if (!langMismatch)
2193             {
2194                 if (contentLangs == String::EMPTY)
2195                 {
2196                     langMismatch = true;
2197                     aggregatedLangs = String::EMPTY;
2198                 }
2199                 else
2200                 {
2201                     if (aggregatedLangs == String::EMPTY)
2202                     {
2203                         aggregatedLangs = contentLangs;
2204                     }
2205                     else if (aggregatedLangs != contentLangs)
2206                     {
2207                         langMismatch = true;
2208                         aggregatedLangs = String::EMPTY;
2209                     }
2210                 }
2211             }
2212
2213             //
2214             //  If a subscription with a duration, calculate subscription
2215             //  time remaining, and add property to the instance
2216             //
2217             if (setTimeRemaining)
2218             {
2219                 try
2220                 {
2221                     _setTimeRemaining(enumInstances[i]);
2222                 }
2223                 catch (DateTimeOutOfRangeException&)
2224                 {
2225                     //
2226                     //  This instance from the repository is invalid
2227                     //  Skip it
2228                     //
2229                     continue;
2230                 }
2231                 if (startTimeAdded)
2232                 {
2233                     enumInstances[i].removeProperty(enumInstances[i].
2234                         findProperty(_PROPERTY_STARTTIME));
2235                 }
2236                 if (durationAdded)
2237                 {
2238                     enumInstances[i].removeProperty(
2239                         enumInstances[i].findProperty(_PROPERTY_DURATION));
2240                 }
2241             }
2242
2243             returnedInstances.append(enumInstances[i]);
2244         }
2245     }
2246
2247     CIMEnumerateInstancesResponseMessage* response =
2248         dynamic_cast<CIMEnumerateInstancesResponseMessage*>(
2249             request->buildResponse());
2250     PEGASUS_ASSERT(response != 0);
2251     if (aggregatedLangs.size())
2252     {
2253         // Note: setting Content-Language in the response to the aggregated
2254         // contentLanguage from the instances in the repository.
2255         response->operationContext.set(ContentLanguageListContainer(
2256             LanguageParser::parseContentLanguageHeader(aggregatedLangs)));
2257     }
2258     response->getResponseData().setInstances(returnedInstances);
2259     _enqueueResponse(request, response);
2260
2261     PEG_METHOD_EXIT();
2262 }
2263
2264 void IndicationService::_handleEnumerateInstanceNamesRequest(
2265     const Message* message)
2266 {
2267     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
2268         "IndicationService::_handleEnumerateInstanceNamesRequest");
2269
2270     CIMEnumerateInstanceNamesRequestMessage* request =
2271         (CIMEnumerateInstanceNamesRequestMessage*) message;
2272
2273     Array<CIMObjectPath> enumInstanceNames;
2274
2275     String userName = ((IdentityContainer)request->operationContext.get(
2276         IdentityContainer::NAME)).getUserName();
2277
2278 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
2279     if (request->className.equal(
2280             PEGASUS_CLASSNAME_CIM_INDICATIONSERVICE) ||
2281         request->className.equal(
2282             PEGASUS_CLASSNAME_CIM_INDICATIONSERVICECAPABILITIES))
2283     {
2284         _checkNonprivilegedAuthorization(userName);
2285         enumInstanceNames = _indicationServiceConfiguration->
2286             enumerateInstanceNamesForClass(
2287                 request->nameSpace,
2288                 request->className);
2289     }
2290     else
2291 #endif
2292
2293 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
2294     if (request->className.equal(PEGASUS_CLASSNAME_PROVIDERINDDATA))
2295     {
2296         enumInstanceNames = _providerIndicationCountTable.
2297             enumerateProviderIndicationDataInstanceNames();
2298     }
2299     else if (request->className.equal(
2300              PEGASUS_CLASSNAME_SUBSCRIPTIONINDDATA))
2301     {
2302         enumInstanceNames = _subscriptionTable->
2303             enumerateSubscriptionIndicationDataInstanceNames();
2304     }
2305     else
2306 #endif
2307     {
2308         _checkNonprivilegedAuthorization(userName);
2309         enumInstanceNames =
2310             _subscriptionRepository->enumerateInstanceNamesForClass(
2311                 request->nameSpace,
2312                 request->className);
2313     }
2314
2315     // Note: not setting Content-Language in the response
2316     CIMEnumerateInstanceNamesResponseMessage* response =
2317         dynamic_cast<CIMEnumerateInstanceNamesResponseMessage *>(
2318             request->buildResponse());
2319     PEGASUS_ASSERT(response != 0);
2320     response->getResponseData().setInstanceNames(enumInstanceNames);
2321     _enqueueResponse(request, response);
2322
2323     PEG_METHOD_EXIT();
2324 }
2325
2326 void IndicationService::_handleModifyInstanceRequest(const Message* message)
2327 {
2328     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
2329         "IndicationService::_handleModifyInstanceRequest");
2330
2331     CIMModifyInstanceRequestMessage* request =
2332         (CIMModifyInstanceRequestMessage*) message;
2333
2334     Boolean responseSent = false;
2335
2336     String userName = ((IdentityContainer)request->operationContext.get(
2337         IdentityContainer::NAME)).getUserName();
2338     _checkNonprivilegedAuthorization(userName);
2339
2340     //
2341     //  Get the instance name
2342     //
2343     CIMObjectPath instanceReference = request->modifiedInstance.getPath();
2344
2345     //
2346     //  Get instance from repository
2347     //
2348     CIMInstance instance;
2349
2350     instance = _subscriptionRepository->getInstance(
2351         request->nameSpace, instanceReference);
2352
2353     CIMInstance modifiedInstance = request->modifiedInstance;
2354     if (_canModify(request, instanceReference, instance, modifiedInstance))
2355     {
2356         //
2357         //  Set path in instance
2358         //
2359         instanceReference.setNameSpace(request->nameSpace);
2360         instance.setPath(instanceReference);
2361
2362         //
2363         //  Check for expired subscription
2364         //
2365         try
2366         {
2367             if (_isExpired(instance))
2368             {
2369                 //
2370                 //  Delete the subscription instance
2371                 //
2372                 _deleteExpiredSubscription(instanceReference);
2373 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
2374                 _sendSubscriptionNotActiveMessagetoHandlerService(
2375                     instanceReference);
2376 #endif
2377                 PEG_METHOD_EXIT();
2378
2379                 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
2380                     MessageLoaderParms(
2381                         "IndicationService.IndicationService._MSG_EXPIRED",
2382                         "An expired subscription cannot be modified:  the "
2383                             "subscription is deleted."));
2384             }
2385         }
2386         catch (DateTimeOutOfRangeException&)
2387         {
2388             //
2389             //  This instance from the repository is invalid
2390             //
2391             PEG_METHOD_EXIT();
2392             throw;
2393         }
2394
2395         //
2396         //  _canModify, above, already checked that propertyList is not
2397         //  null, and that numProperties is 0 or 1
2398         //
2399         CIMPropertyList propertyList = request->propertyList;
2400         if (request->propertyList.size() > 0)
2401         {
2402             //
2403             //  Get current state from instance
2404             //
2405             Uint16 currentState;
2406             Boolean valid = true;
2407             if (_subscriptionRepository->getState(instance, currentState))
2408             {
2409                 valid = _validateState(currentState);
2410             }
2411
2412             if (!valid)
2413             {
2414                 //
2415                 //  This instance from the repository is corrupted
2416                 //
2417                 PEG_METHOD_EXIT();
2418                 MessageLoaderParms parms(_MSG_INVALID_INSTANCES_KEY,
2419                     _MSG_INVALID_INSTANCES);
2420                 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, parms);
2421             }
2422
2423             //
2424             //  Get new state
2425             //
2426             //  NOTE: _canModify has already validated the
2427             //  SubscriptionState property in the instance; if missing, it
2428             //  was added with the default value; if null, it was set to
2429             //  the default value; if invalid, an exception was thrown
2430             //
2431             Uint16 newState;
2432             modifiedInstance.getProperty(modifiedInstance.findProperty(
2433                 PEGASUS_PROPERTYNAME_SUBSCRIPTION_STATE)).getValue().get(
2434                     newState);
2435
2436             //
2437             //  If Subscription State has changed,
2438             //  Set Time of Last State Change to current date time
2439             //
2440             CIMDateTime currentDateTime =
2441                 CIMDateTime::getCurrentDateTime();
2442             if (newState != currentState)
2443             {
2444                 if (modifiedInstance.findProperty(_PROPERTY_LASTCHANGE) !=
2445                     PEG_NOT_FOUND)
2446                 {
2447                     CIMProperty lastChange = modifiedInstance.getProperty(
2448                         modifiedInstance.findProperty(
2449                             _PROPERTY_LASTCHANGE));
2450                     lastChange.setValue(CIMValue(currentDateTime));
2451                 }
2452                 else
2453                 {
2454                     modifiedInstance.addProperty(CIMProperty(
2455                         _PROPERTY_LASTCHANGE, CIMValue(currentDateTime)));
2456                 }
2457                 Array<CIMName> properties =
2458                     propertyList.getPropertyNameArray();
2459                 properties.append(_PROPERTY_LASTCHANGE);
2460                 propertyList.set(properties);
2461             }
2462
2463             //
2464             //  If Subscription is to be enabled, and this is the first
2465             //  time, set Subscription Start Time
2466             //
2467             if ((newState == STATE_ENABLED) ||
2468                 (newState == STATE_ENABLEDDEGRADED))
2469             {
2470                 //
2471                 //  If Subscription Start Time is null, set value
2472                 //  to the current date time
2473                 //
2474                 CIMDateTime startTime;
2475                 CIMProperty startTimeProperty = instance.getProperty(
2476                     instance.findProperty(_PROPERTY_STARTTIME));
2477                 CIMValue startTimeValue = startTimeProperty.getValue();
2478                 Boolean setStart = false;
2479                 if (startTimeValue.isNull())
2480                 {
2481                     setStart = true;
2482                 }
2483                 else
2484                 {
2485                     startTimeValue.get(startTime);
2486
2487                     if (startTime.isInterval())
2488                     {
2489                         if (startTime.equal(
2490                                 CIMDateTime(_ZERO_INTERVAL_STRING)))
2491                         {
2492                             setStart = true;
2493                         }
2494                     }
2495                 }
2496
2497                 if (setStart)
2498                 {
2499                     if (modifiedInstance.findProperty(_PROPERTY_STARTTIME)
2500                         != PEG_NOT_FOUND)
2501                     {
2502                         CIMProperty startTimeProperty =
2503                             modifiedInstance.getProperty(
2504                                 modifiedInstance.findProperty(
2505                                     _PROPERTY_STARTTIME));
2506                         startTimeProperty.setValue(CIMValue(currentDateTime));
2507                     }
2508                     else
2509                     {
2510                         modifiedInstance.addProperty(CIMProperty(
2511                             _PROPERTY_STARTTIME,
2512                             CIMValue(currentDateTime)));
2513                     }
2514
2515                     Array<CIMName> properties =
2516                         propertyList.getPropertyNameArray();
2517                     properties.append(_PROPERTY_STARTTIME);
2518                     propertyList.set(properties);
2519                 }
2520             }
2521
2522             // Add the language properties to the modified instance.
2523             // Note:  These came from the Accept-Language and
2524             // Content-Language headers in the HTTP messages, and may be
2525             // empty.
2526             AcceptLanguageList acceptLangs =
2527                 ((AcceptLanguageListContainer)request->operationContext.get(
2528                 AcceptLanguageListContainer::NAME)).getLanguages();
2529             modifiedInstance.addProperty(CIMProperty(
2530                 PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS,
2531                 LanguageParser::buildAcceptLanguageHeader(acceptLangs)));
2532
2533             ContentLanguageList contentLangs =
2534                 ((ContentLanguageListContainer)request->operationContext.get
2535                 (ContentLanguageListContainer::NAME)).getLanguages();
2536             modifiedInstance.addProperty (CIMProperty
2537                 (PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS,
2538                 LanguageParser::buildContentLanguageHeader(contentLangs)));
2539
2540             Array<CIMName> properties = propertyList.getPropertyNameArray();
2541             properties.append (PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS);
2542             properties.append (PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS);
2543             propertyList.set (properties);
2544
2545             //
2546             //  If subscription is to be enabled, determine if there are
2547             //  any indication providers that can serve the subscription
2548             //
2549             Array<ProviderClassList> indicationProviders;
2550             CIMPropertyList requiredProperties;
2551             CIMNamespaceName sourceNameSpace;
2552             String condition;
2553             String query;
2554             String queryLanguage;
2555             Array<CIMName> indicationSubclasses;
2556
2557             if (((newState == STATE_ENABLED) ||
2558                  (newState == STATE_ENABLEDDEGRADED))
2559                 && ((currentState != STATE_ENABLED) &&
2560                     (currentState != STATE_ENABLEDDEGRADED)))
2561             {
2562                 //
2563                 //  Subscription was previously not enabled but is now to
2564                 //  be enabled
2565                 //
2566                 _getCreateParams(instance, indicationSubclasses,
2567                     indicationProviders, requiredProperties,
2568                     sourceNameSpace, condition, query, queryLanguage);
2569
2570                 if (indicationProviders.size() == 0)
2571                 {
2572                     //
2573                     //  There are no providers that can support this
2574                     //  subscription
2575                     //
2576                     instance.setPath(instanceReference);
2577                     _subscriptionRepository->reconcileFatalError(instance);
2578                     PEG_METHOD_EXIT();
2579
2580                     throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_NOT_SUPPORTED,
2581                         MessageLoaderParms(_MSG_NO_PROVIDERS_KEY,
2582                         _MSG_NO_PROVIDERS));
2583                 }
2584             }
2585
2586             //
2587             //  Modify the instance in the repository
2588             //
2589             modifiedInstance.setPath(instanceReference);
2590             _subscriptionRepository->modifyInstance(
2591                 request->nameSpace, modifiedInstance,
2592                 request->includeQualifiers, propertyList);
2593
2594             PEG_TRACE((
2595                 TRC_INDICATION_SERVICE,
2596                 Tracer::LEVEL3,
2597                 "IndicationService::_handleModifyInstanceRequest - "
2598                     "Name Space: %s  Instance name: %s",
2599                 (const char*)
2600                 request->nameSpace.getString().getCString(),
2601                 (const char*)
2602                 modifiedInstance.getClassName().getString().getCString()
2603             ));
2604
2605             //
2606             //  If subscription is newly enabled, send Create requests
2607             //  and enable providers
2608             //
2609             if (((newState == STATE_ENABLED) ||
2610                  (newState == STATE_ENABLEDDEGRADED))
2611                 && ((currentState != STATE_ENABLED) &&
2612                     (currentState != STATE_ENABLEDDEGRADED)))
2613             {
2614                 instanceReference.setNameSpace(request->nameSpace);
2615                 instance.setPath(instanceReference);
2616
2617                 _sendAsyncCreateRequests(
2618                     indicationProviders,
2619                     sourceNameSpace,
2620                     requiredProperties,
2621                     condition,
2622                     query,
2623                     queryLanguage,
2624                     instance,
2625                     acceptLangs,
2626                     contentLangs,
2627                     request,
2628                     indicationSubclasses,
2629                     userName,
2630                     request->authType);
2631
2632                 //
2633                 //  Response is sent from _handleCreateResponseAggregation
2634                 //
2635                 responseSent = true;
2636             }
2637             else if ((newState == STATE_DISABLED) &&
2638                      ((currentState == STATE_ENABLED) ||
2639                       (currentState == STATE_ENABLEDDEGRADED)))
2640             {
2641                 //
2642                 //  Subscription was previously enabled but is now to be
2643                 //  disabled
2644                 //
2645                 instanceReference.setNameSpace(request->nameSpace);
2646                 instance.setPath(instanceReference);
2647                 indicationProviders = _getDeleteParams(instance,
2648                     indicationSubclasses, sourceNameSpace);
2649
2650                 //
2651                 //  Send Delete requests
2652                 //
2653                 if (indicationProviders.size() > 0)
2654                 {
2655                     _sendAsyncDeleteRequests(
2656                         indicationProviders,
2657                         sourceNameSpace,
2658                         instance,
2659                         acceptLangs,
2660                         contentLangs,
2661                         request,
2662                         indicationSubclasses,
2663                         userName,
2664                         request->authType);
2665
2666                     //
2667                     //  Response is sent from
2668                     //  _handleDeleteResponseAggregation
2669                     //
2670                     responseSent = true;
2671 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
2672                     _sendSubscriptionNotActiveMessagetoHandlerService(
2673                         instanceReference);
2674 #endif
2675                 }
2676             }
2677         }
2678     }
2679
2680     //
2681     //  Send response, if not sent from callback
2682     //  (for example, if there are no indication providers that can support a
2683     //  subscription)
2684     //
2685     if (!responseSent)
2686     {
2687         // Note: don't need to set content-language in the response.
2688         CIMResponseMessage * response = request->buildResponse();
2689         _enqueueResponse(request, response);
2690     }
2691
2692     PEG_METHOD_EXIT();
2693 }
2694
2695 void IndicationService::_handleDeleteInstanceRequest(const Message* message)
2696 {
2697     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
2698         "IndicationService::_handleDeleteInstanceRequest");
2699
2700     CIMDeleteInstanceRequestMessage* request =
2701         (CIMDeleteInstanceRequestMessage*) message;
2702
2703     Boolean responseSent = false;
2704
2705     String userName = ((IdentityContainer)request->operationContext.get(
2706         IdentityContainer::NAME)).getUserName();
2707     _checkNonprivilegedAuthorization(userName);
2708
2709     //
2710     //  Check if instance may be deleted -- a filter or handler instance
2711     //  referenced by a subscription instance may not be deleted
2712     //
2713     if (_canDelete(request->instanceName, request->nameSpace, userName))
2714     {
2715         //
2716         //  If a subscription, get the instance from the repository
2717         //
2718         CIMInstance subscriptionInstance;
2719         if (request->instanceName.getClassName().equal(
2720                 PEGASUS_CLASSNAME_INDSUBSCRIPTION) ||
2721             request->instanceName.getClassName ().equal(
2722                 PEGASUS_CLASSNAME_FORMATTEDINDSUBSCRIPTION))
2723         {
2724             subscriptionInstance =
2725                 _subscriptionRepository->getInstance(
2726                     request->nameSpace, request->instanceName);
2727         }
2728
2729         //
2730         //  Delete instance from repository
2731         //
2732         _subscriptionRepository->deleteInstance(
2733             request->nameSpace, request->instanceName);
2734
2735 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
2736         if (request->instanceName.getClassName().equal(
2737                 PEGASUS_CLASSNAME_LSTNRDST_CIMXML) ||
2738             request->instanceName.getClassName().equal(
2739                PEGASUS_CLASSNAME_INDHANDLER_CIMXML))
2740         {
2741             CIMObjectPath handlerName = request->instanceName;
2742             handlerName.setNameSpace(request->nameSpace);
2743             _sendListenerNotActiveMessagetoHandlerService(handlerName);
2744         }
2745 #endif
2746
2747         PEG_TRACE((
2748             TRC_INDICATION_SERVICE,
2749             Tracer::LEVEL3,
2750             "IndicationService::_handleDeleteInstanceRequest - "
2751                 "Name Space: %s  Instance name: %s",
2752             (const char*) request->nameSpace.getString().getCString(),
2753             (const char*)
2754            request->instanceName.getClassName().getString().getCString()
2755         ));
2756
2757         if (request->instanceName.getClassName().equal(
2758                 PEGASUS_CLASSNAME_INDSUBSCRIPTION) ||
2759             request->instanceName.getClassName ().equal(
2760                 PEGASUS_CLASSNAME_FORMATTEDINDSUBSCRIPTION))
2761         {
2762             //
2763             //  If subscription is active, send delete requests to providers
2764             //  and update hash tables
2765             //
2766             Uint16 subscriptionState;
2767             CIMValue subscriptionStateValue;
2768             subscriptionStateValue = subscriptionInstance.getProperty(
2769                 subscriptionInstance.findProperty(
2770                     PEGASUS_PROPERTYNAME_SUBSCRIPTION_STATE)).getValue();
2771             subscriptionStateValue.get(subscriptionState);
2772
2773             if ((subscriptionState == STATE_ENABLED) ||
2774                 (subscriptionState == STATE_ENABLEDDEGRADED))
2775             {
2776                 Array<ProviderClassList> indicationProviders;
2777                 Array<CIMName> indicationSubclasses;
2778                 CIMNamespaceName sourceNamespaceName;
2779                 CIMObjectPath instanceReference = request->instanceName;
2780                 instanceReference.setNameSpace(request->nameSpace);
2781                 subscriptionInstance.setPath(instanceReference);
2782
2783                 indicationProviders = _getDeleteParams(
2784                     subscriptionInstance,
2785                     indicationSubclasses,
2786                     sourceNamespaceName);
2787
2788                 if (indicationProviders.size() > 0)
2789                 {
2790                     //
2791                     //  Send Delete requests
2792                     //
2793                     _sendAsyncDeleteRequests(
2794                         indicationProviders,
2795                         sourceNamespaceName,
2796                         subscriptionInstance,
2797                         ((AcceptLanguageListContainer)
2798                             request->operationContext.get(
2799                                 AcceptLanguageListContainer::NAME)).
2800                                     getLanguages(),
2801                         ((ContentLanguageListContainer)
2802                             request->operationContext.get(
2803                                 ContentLanguageListContainer::NAME)).
2804                                     getLanguages(),
2805                         request,
2806                         indicationSubclasses,
2807                         userName,
2808                         request->authType);
2809
2810                     //
2811                     //  Response is sent from
2812                     //  _handleDeleteResponseAggregation
2813                     //
2814                     responseSent = true;
2815 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
2816                     _sendSubscriptionNotActiveMessagetoHandlerService(
2817                         instanceReference);
2818 #endif
2819                 }
2820                 else
2821                 {
2822                     //
2823                     //  Subscription was enabled, but had no providers
2824                     //  Remove entries from the subscription hash tables
2825                     //
2826                     _subscriptionTable->removeSubscription(
2827                         subscriptionInstance,
2828                         indicationSubclasses,
2829                         sourceNamespaceName,
2830                         indicationProviders);
2831                 }
2832             }
2833         }
2834     }
2835
2836     //
2837     //  Send response, if not sent from callback
2838     //  (for example, if a subscription had no indication providers)
2839     //
2840     if (!responseSent)
2841     {
2842         CIMResponseMessage * response = request->buildResponse();
2843         _enqueueResponse(request, response);
2844     }
2845
2846     PEG_METHOD_EXIT();
2847 }
2848
2849 // l10n TODO - might need to globalize another flow and another consumer
2850 // interface (ie. mdd's) if we can't agree on one export flow and consumer
2851 // interface (see PEP67)
2852
2853 void IndicationService::_handleProcessIndicationRequest(Message* message)
2854 {
2855
2856 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
2857     _processIndicationThreads++;
2858     AutoPtr<AtomicInt, DecAtomicInt> counter(&_processIndicationThreads);
2859 #endif
2860
2861 #ifdef PEGASUS_INDICATION_PERFINST
2862     Stopwatch stopWatch;
2863 #endif
2864
2865     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
2866         "IndicationService::_handleProcessIndicationRequest");
2867
2868 #ifdef PEGASUS_INDICATION_PERFINST
2869         stopWatch.reset();
2870         stopWatch.start();
2871 #endif
2872
2873     CIMProcessIndicationRequestMessage* request = dynamic_cast<
2874         CIMProcessIndicationRequestMessage*> (message);
2875     PEGASUS_ASSERT(request != 0);
2876
2877     Array<CIMInstance> matchedSubscriptions;
2878     Array<String> matchedSubscriptionsKeys;
2879
2880     CIMInstance indication = request->indicationInstance;
2881
2882     try
2883     {
2884         PEG_TRACE ((TRC_INDICATION_GENERATION, Tracer::LEVEL4,
2885            "Received %s Indication %s from namespace %s from provider %s",
2886            (const char*)(indication.getClassName().getString().getCString()),
2887            (const char*)(request->messageId.getCString()),
2888            (const char*)(request->nameSpace.getString().getCString()),
2889            (const char*)(request->provider.getProperty(request->provider.
2890                findProperty(PEGASUS_PROPERTYNAME_NAME)).getValue().toString().
2891                    getCString())));
2892
2893         //
2894         // Get supported properties by the indication provider
2895         // Get Indication class properties
2896         // Check if the provider supports all properties of the indication
2897         // class, if so, set to null
2898         //
2899         Array<CIMName> providerSupportedProperties;
2900         Array<CIMName> indicationClassProperties;
2901         CIMPropertyList supportedPropertyList;
2902
2903         for (Uint32 i = 0; i < indication.getPropertyCount(); i++)
2904         {
2905             providerSupportedProperties.append(
2906                 indication.getProperty(i).getName());
2907         }
2908
2909         supportedPropertyList = _checkPropertyList(providerSupportedProperties,
2910                                                    request->nameSpace,
2911                                                    indication.getClassName(),
2912                                                    indicationClassProperties);
2913
2914         //
2915         // Get initial subscriptions based on the class name, namespace
2916         // of the generated indication, and subscriptions specified by the
2917         // indication provider if the provider included subscriptions
2918         // in the subscriptionInstanceNamesContainer
2919         //
2920         Array<CIMInstance> subscriptions;
2921         Array<String> subscriptionKeys;
2922         _getRelevantSubscriptions(
2923             request->subscriptionInstanceNames,
2924             indication.getClassName(),
2925             request->nameSpace,
2926             request->provider,
2927             subscriptions,
2928             subscriptionKeys);
2929
2930         for (Uint32 i = 0; i < subscriptions.size(); i++)
2931         {
2932             try
2933             {
2934                 QueryExpression queryExpr;
2935                 String filterQuery;
2936                 String queryLanguage;
2937                 String filterName;
2938                 CIMNamespaceName sourceNameSpace;
2939
2940                 //
2941                 //  Get filter query expression of the subscription
2942                 //
2943                 _subscriptionRepository->getFilterProperties
2944                     (subscriptions[i], filterQuery, sourceNameSpace,
2945                      queryLanguage, filterName);
2946
2947                 queryExpr = _getQueryExpression(
2948                     filterQuery, queryLanguage, sourceNameSpace);
2949
2950                 //
2951                 // Evaluate if the subscription matches the indication by
2952                 // checking:
2953                 // 1) Whether the properties (in WHERE clause) from filter
2954                 //    query are supported by the indication provider;
2955                 // 2) Whether the subscripton is expired;
2956                 // 3) Whether the filter criteria are met by the generated
2957                 //    indication
2958                 //
2959                 if (_subscriptionMatch (subscriptions[i], indication,
2960                     supportedPropertyList, queryExpr, sourceNameSpace))
2961                 {
2962                     PEG_TRACE ((TRC_INDICATION_GENERATION, Tracer::LEVEL4,
2963                         "%s Indication %s satisfies filter %s:%s query "
2964                             "expression  \"%s\"",
2965                             (const char*)(indication.getClassName().
2966                                 getString().getCString()),
2967                             (const char*)(request->messageId.getCString()),
2968                             (const char*)(sourceNameSpace.getString().
2969                                 getCString()),
2970                             (const char*)(filterName.getCString()),
2971                             (const char*)(filterQuery.getCString())));
2972
2973                     //
2974                     // Format the indication
2975                     // This includes two parts:
2976                     // 1) Use QueryExpression::applyProjection to remove
2977                     //    properties not listed in the SELECT clause;
2978                     // 2) Remove any properties that may be left on the
2979                     //    indication that are not in the indication class.
2980                     //    These are properties added by the provider
2981                     //    incorrectly.
2982                     //
2983                     CIMInstance formattedIndication = indication.clone();
2984
2985                     if (_formatIndication(formattedIndication,
2986                                           queryExpr,
2987                                           providerSupportedProperties,
2988                                           indicationClassProperties))
2989                     {
2990                         //
2991                         // get the handler instance and forward the formatted
2992                         // indication to the handler
2993                         //
2994                         CIMInstance handlerInstance =
2995                             _subscriptionRepository->getHandler(
2996                                 subscriptions[i]);
2997
2998                         PEG_TRACE((TRC_INDICATION_GENERATION, Tracer::LEVEL4,
2999                             "Handler %s:%s.%s found for %s Indication %s",
3000                             (const char*)(request->nameSpace.getString().
3001                                 getCString()),
3002                             (const char*)(handlerInstance.getClassName().
3003                                 getString().getCString()),
3004                             (const char*)(handlerInstance.getProperty(
3005                                 handlerInstance.findProperty(
3006                                     PEGASUS_PROPERTYNAME_NAME)).getValue().
3007                                         toString().getCString()),
3008                             (const char*)(indication.getClassName().
3009                                 getString().getCString()),
3010                             (const char*)(request->messageId.getCString())));
3011
3012                         _forwardIndToHandler(subscriptions[i],
3013                                              handlerInstance,
3014                                              formattedIndication,
3015                                              request->nameSpace,
3016                                              request->operationContext);
3017
3018                         matchedSubscriptions.append(subscriptions[i]);
3019                         matchedSubscriptionsKeys.append(subscriptionKeys[i]);
3020                     }
3021                 }
3022             }
3023             catch (Exception& e)
3024             {
3025                 PEG_TRACE ((TRC_DISCARDED_DATA, Tracer::LEVEL1,
3026                     "Exception caught in attempting to process indication "
3027                         "for the subscription %s: %s",
3028                         (const char *) subscriptions[i].getPath ().toString().
3029                             getCString(),
3030                         (const char *) e.getMessage ().getCString()));
3031             }
3032             catch (exception& e)
3033             {
3034                 PEG_TRACE ((TRC_DISCARDED_DATA, Tracer::LEVEL1,
3035                     "Exception caught in attempting to process indication "
3036                         "for the subscription %s: %s",
3037                     (const char *) subscriptions[i].getPath ().toString().
3038                         getCString(), e.what()));
3039            }
3040            catch (...)
3041            {
3042                PEG_TRACE ((TRC_DISCARDED_DATA, Tracer::LEVEL1,
3043                    "Unknown exception caught in attempting to process "
3044                        "indication for the subscription %s",
3045                     (const char *) subscriptions[i].getPath ().toString ().
3046                         getCString()));
3047            }
3048
3049         }
3050
3051 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
3052         _providerIndicationCountTable.incrementEntry(
3053             request->provider, matchedSubscriptions.size() == 0);
3054         _subscriptionTable->updateMatchedIndicationCounts(
3055             request->provider, matchedSubscriptionsKeys);
3056 #endif
3057
3058         //
3059         //  Log subscriptions info to a trace message
3060         //
3061         if (matchedSubscriptions.size() == 0)
3062         {
3063            PEG_TRACE ((TRC_INDICATION_GENERATION, Tracer::LEVEL1,
3064                "No matching subscriptions found for %s Indication %s",
3065                (const char*)(indication.getClassName().getString().
3066                    getCString()),
3067                (const char*)(request->messageId.getCString())));
3068         }
3069         else
3070         {
3071             PEG_TRACE ((TRC_INDICATION_GENERATION, Tracer::LEVEL4,
3072                 "%d subscriptions found for %s Indication %s in namespace %s",
3073                 matchedSubscriptions.size(),
3074                 (const char*)(indication.getClassName().getString().
3075                     getCString()),
3076                 (const char*)(request->messageId.getCString()),
3077                 (const char*)(request->nameSpace.getString().getCString())));
3078         }
3079     }
3080     catch (Exception& e)
3081     {
3082         PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL1,
3083             "Exception caught while processing indication: %s.  "
3084                 "Indication may be lost.",
3085             (const char*)e.getMessage().getCString()));
3086         PEG_METHOD_EXIT();
3087         throw;
3088     }
3089     catch (...)
3090     {
3091         PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
3092             "Exception caught while processing indication.  Indication may be "
3093                 "lost.");
3094         PEG_METHOD_EXIT();
3095         throw;
3096     }
3097
3098     _enqueueResponse(request, request->buildResponse());
3099
3100 #ifdef PEGASUS_INDICATION_PERFINST
3101     stopWatch.stop();
3102
3103     PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
3104         "%s: %.3f seconds", "Process Indication", stopWatch.getElapsed()));
3105 #endif
3106
3107     PEG_METHOD_EXIT ();
3108     return;
3109 }
3110
3111 void IndicationService::_handleIndicationCallBack (
3112     AsyncOpNode * operation,
3113     MessageQueue * destination,
3114     void * userParameter)
3115 {
3116     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
3117         "IndicationService::_handleIndicationCallBack");
3118
3119     IndicationService * service =
3120         static_cast<IndicationService *> (destination);
3121     CIMInstance * subscription =
3122         reinterpret_cast<CIMInstance *> (userParameter);
3123     AsyncReply * asyncReply =
3124         static_cast<AsyncReply *>(operation->removeResponse());
3125     CIMHandleIndicationResponseMessage* handlerResponse =
3126         reinterpret_cast<CIMHandleIndicationResponseMessage *>(
3127             (static_cast<AsyncLegacyOperationResult *>(
3128                 asyncReply))->get_result());
3129     PEGASUS_ASSERT (handlerResponse != 0);
3130
3131     if (handlerResponse->cimException.getCode () != CIM_ERR_SUCCESS)
3132     {
3133         PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL1,
3134             "Sending Indication and HandlerService returns CIMException: %s",
3135             (const char*)
3136                 handlerResponse->cimException.getMessage().getCString()));
3137
3138         //
3139         //  ATTN-CAKG-P1-20020326: Implement subscription's OnFatalErrorPolicy
3140         //
3141         //service->_subscriptionRepository->reconcileFatalError (*subscription);
3142     }
3143
3144     delete handlerResponse;
3145     delete asyncReply;
3146     service->return_op (operation);
3147
3148     PEG_METHOD_EXIT ();
3149 }
3150
3151 void IndicationService::_handleNotifyProviderRegistrationRequest
3152     (const Message* message)
3153 {
3154     PEG_METHOD_ENTER ( TRC_INDICATION_SERVICE,
3155         "IndicationService::_handleNotifyProviderRegistrationRequest");
3156
3157     CIMNotifyProviderRegistrationRequestMessage* request =
3158         (CIMNotifyProviderRegistrationRequestMessage*) message;
3159
3160     ProviderIdContainer pidc = request->operationContext.get
3161         (ProviderIdContainer::NAME);
3162     CIMInstance provider = pidc.getProvider();
3163     CIMInstance providerModule = pidc.getModule();
3164 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
3165     Boolean isRemoteNameSpace = pidc.isRemoteNameSpace();
3166     String remoteInfo = pidc.getRemoteInfo();
3167 #endif
3168
3169     CIMName className = request->className;
3170     Array<CIMNamespaceName> newNameSpaces = request->newNamespaces;
3171     Array<CIMNamespaceName> oldNameSpaces = request->oldNamespaces;
3172     CIMPropertyList newPropertyNames = request->newPropertyNames;
3173     CIMPropertyList oldPropertyNames = request->oldPropertyNames;
3174
3175     Array<CIMInstance> newSubscriptions;
3176     Array<CIMInstance> formerSubscriptions;
3177     Array<ProviderClassList> indicationProviders;
3178     ProviderClassList indicationProvider;
3179
3180     newSubscriptions.clear ();
3181     formerSubscriptions.clear ();
3182
3183     switch (request->operation)
3184     {
3185         case OP_CREATE:
3186         {
3187             //
3188             //  Get matching subscriptions
3189             //
3190             newSubscriptions = _getMatchingSubscriptions (className,
3191                 newNameSpaces, newPropertyNames);
3192
3193             break;
3194         }
3195
3196         case OP_DELETE:
3197         {
3198             //
3199             //  Get matching subscriptions
3200             //
3201             formerSubscriptions = _getMatchingSubscriptions (className,
3202                 oldNameSpaces, oldPropertyNames);
3203
3204 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
3205             _providerIndicationCountTable.removeEntry(provider);
3206 #endif
3207
3208             break;
3209         }
3210
3211         case OP_MODIFY:
3212         {
3213             //
3214             //  Get lists of affected subscriptions
3215             //
3216             _getModifiedSubscriptions (className, newNameSpaces, oldNameSpaces,
3217                 newPropertyNames, oldPropertyNames,
3218                 newSubscriptions, formerSubscriptions);
3219
3220             break;
3221         }
3222         default:
3223             //
3224             //  Error condition: operation not supported
3225             //
3226             PEG_METHOD_EXIT ();
3227             throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, String::EMPTY);
3228             break;
3229     }  // switch
3230
3231     //
3232     //  Construct provider class list from input provider and class name
3233     //
3234     indicationProvider.provider = provider;
3235     indicationProvider.providerModule = providerModule;
3236     indicationProvider.classList.append (className);
3237 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
3238     indicationProvider.isRemoteNameSpace = isRemoteNameSpace;
3239     indicationProvider.remoteInfo = remoteInfo;
3240 #endif
3241     indicationProviders.append (indicationProvider);
3242
3243     if (newSubscriptions.size () > 0)
3244     {
3245         CIMPropertyList requiredProperties;
3246         String condition;
3247         String query;
3248         String queryLanguage;
3249
3250         //
3251         //  Send Create or Modify request for each subscription that can newly
3252         //  be supported
3253         //
3254         for (Uint32 i = 0; i < newSubscriptions.size (); i++)
3255         {
3256             CIMNamespaceName sourceNameSpace;
3257             Array<CIMName> indicationSubclasses;
3258             _getCreateParams (newSubscriptions[i], indicationSubclasses,
3259                 requiredProperties, sourceNameSpace, condition,
3260                 query, queryLanguage);
3261
3262             //
3263             //  NOTE: These Create or Modify requests are not associated with a
3264             //  user request, so there is no associated authType or userName
3265             //  The Creator from the subscription instance is used for
3266             //  userName, and authType is not set
3267             //
3268             //  NOTE: the subscriptions in the newSubscriptions list came from
3269             //  the IndicationService's internal hash tables, and thus
3270             //  each instance is known to have a valid Creator property
3271             //
3272             CIMInstance instance = newSubscriptions[i];
3273             String creator = instance.getProperty (instance.findProperty
3274                 (PEGASUS_PROPERTYNAME_INDSUB_CREATOR)).getValue ().toString ();
3275
3276 // l10n start
3277             AcceptLanguageList acceptLangs;
3278             Uint32 propIndex = instance.findProperty
3279                 (PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS);
3280             if (propIndex != PEG_NOT_FOUND)
3281             {
3282                 String acceptLangsString;
3283                 instance.getProperty(propIndex).getValue().get(
3284                     acceptLangsString);
3285                 if (acceptLangsString.size())
3286                 {
3287                     acceptLangs = LanguageParser::parseAcceptLanguageHeader(
3288                         acceptLangsString);
3289                 }
3290             }
3291             ContentLanguageList contentLangs;
3292             propIndex = instance.findProperty
3293                 (PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS);
3294             if (propIndex != PEG_NOT_FOUND)
3295             {
3296                 String contentLangsString;
3297                 instance.getProperty(propIndex).getValue().get(
3298                     contentLangsString);
3299                 if (contentLangsString.size())
3300                 {
3301                     contentLangs = LanguageParser::parseContentLanguageHeader(
3302                         contentLangsString);
3303                 }
3304             }
3305 // l10n end
3306
3307             //
3308             //  Look up the subscription in the active subscriptions table
3309             //
3310             ActiveSubscriptionsTableEntry tableValue;
3311             if (_subscriptionTable->getSubscriptionEntry
3312                 (newSubscriptions[i].getPath (), tableValue))
3313             {
3314                 //
3315                 //  If the provider is already in the subscription's list,
3316                 //  send a Modify request, otherwise send a Create request
3317                 //
3318                 Uint32 providerIndex = _subscriptionTable->providerInList
3319                     (provider, tableValue);
3320                 if (providerIndex != PEG_NOT_FOUND)
3321                 {
3322                     //
3323                     //  Send Modify requests
3324                     //
3325                     _sendWaitModifyRequests (indicationProviders,
3326                         sourceNameSpace,
3327                         requiredProperties, condition, query, queryLanguage,
3328                         newSubscriptions[i],
3329                         acceptLangs,
3330                         contentLangs,
3331                         creator);
3332                 }
3333                 else
3334                 {
3335                     //
3336                     //  Send Create requests
3337                     //
3338                     Array<ProviderClassList> acceptedProviders;
3339                     acceptedProviders = _sendWaitCreateRequests
3340                         (indicationProviders,
3341                         sourceNameSpace, requiredProperties, condition,
3342                         query, queryLanguage, newSubscriptions[i],
3343                         acceptLangs,
3344                         contentLangs,
3345                         creator);
3346
3347                     if (acceptedProviders.size () > 0)
3348                     {
3349                         //
3350                         //  Provider is not yet in the list for this
3351                         //  subscription; add provider to the list
3352                         //
3353                         _subscriptionTable->updateProviders
3354                             (instance.getPath (), indicationProvider, true);
3355                     }
3356                 }
3357             }
3358             else
3359             {
3360                 //
3361                 //  Subscription not found in Active Subscriptions table
3362                 //
3363             }
3364         }
3365
3366         //
3367         //  NOTE: When a provider that was previously not serving a subscription
3368         //  now serves the subscription due to a provider registration change,
3369         //  a log message is sent, even if there were previously other providers
3370         //  serving the subscription
3371         //
3372
3373         //
3374         //  Log a message for each subscription
3375         //
3376         CIMClass providerClass = _subscriptionRepository->getClass
3377             (PEGASUS_NAMESPACENAME_INTEROP, PEGASUS_CLASSNAME_PROVIDER,
3378              true, true, false, CIMPropertyList ());
3379         CIMInstance providerCopy = provider.clone ();
3380         CIMObjectPath path = providerCopy.buildPath (providerClass);
3381         providerCopy.setPath (path);
3382         String logString1 = getProviderLogString (providerCopy);
3383
3384         for (Uint32 j = 0; j < newSubscriptions.size (); j++)
3385         {
3386             //
3387             //  Get Provider Name, Subscription Filter Name and Handler Name
3388             //
3389             String logString2 = _getSubscriptionLogString
3390                 (newSubscriptions[j]);
3391
3392             Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
3393                 Logger::WARNING,
3394                 MessageLoaderParms(
3395                     _MSG_PROVIDER_NOW_SERVING_KEY,
3396                     _MSG_PROVIDER_NOW_SERVING, logString1, logString2,
3397                     newSubscriptions[j].getPath().getNameSpace().getString()));
3398         }
3399     }
3400
3401     if (formerSubscriptions.size () > 0)
3402     {
3403         CIMPropertyList requiredProperties;
3404         String condition;
3405         String query;
3406         String queryLanguage;
3407
3408         //
3409         //  Send Delete or Modify request for each subscription that can no
3410         //  longer be supported
3411         //
3412         for (Uint32 i = 0; i < formerSubscriptions.size (); i++)
3413         {
3414             //
3415             //  NOTE: These Delete or Modify requests are not associated with a
3416             //  user request, so there is no associated authType or userName
3417             //  The Creator from the subscription instance is used for userName,
3418             //  and authType is not set
3419             //
3420             //  NOTE: the subscriptions in the formerSubscriptions list came
3421             //  from the IndicationService's internal hash tables, and thus
3422             //  each instance is known to have a valid Creator property
3423             //
3424             CIMInstance instance = formerSubscriptions[i];
3425             String creator = instance.getProperty (instance.findProperty
3426                 (PEGASUS_PROPERTYNAME_INDSUB_CREATOR)).getValue ().toString ();
3427             AcceptLanguageList acceptLangs;
3428             Uint32 propIndex = instance.findProperty
3429                 (PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS);
3430             if (propIndex != PEG_NOT_FOUND)
3431             {
3432                 String acceptLangsString;
3433                 instance.getProperty(propIndex).getValue().get(
3434                     acceptLangsString);
3435                 if (acceptLangsString.size())
3436                 {
3437                     acceptLangs = LanguageParser::parseAcceptLanguageHeader(
3438                         acceptLangsString);
3439                 }
3440             }
3441             ContentLanguageList contentLangs;
3442             propIndex = instance.findProperty
3443                 (PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS);
3444             if (propIndex != PEG_NOT_FOUND)
3445             {
3446                 String contentLangsString;
3447                 instance.getProperty(propIndex).getValue().get(
3448                     contentLangsString);
3449                 if (contentLangsString.size())
3450                 {
3451                     contentLangs = LanguageParser::parseContentLanguageHeader(
3452                         contentLangsString);
3453                 }
3454             }
3455
3456             //
3457             //  Look up the subscription in the active subscriptions table
3458             //  If class list contains only the class name from the current
3459             //  operation, send a Delete request
3460             //  Otherwise, send a Modify request
3461             //
3462             ActiveSubscriptionsTableEntry tableValue;
3463             if (_subscriptionTable->getSubscriptionEntry
3464                 (formerSubscriptions[i].getPath (), tableValue))
3465             {
3466                 Uint32 providerIndex = _subscriptionTable->providerInList
3467                     (provider, tableValue);
3468                 if (providerIndex != PEG_NOT_FOUND)
3469                 {
3470                     CIMNamespaceName sourceNameSpace;
3471                     Array<CIMName> indicationSubclasses;
3472                     _getCreateParams (formerSubscriptions[i],
3473                         indicationSubclasses, requiredProperties,
3474                         sourceNameSpace, condition, query, queryLanguage);
3475
3476                     //
3477                     //  If class list contains only the class name from the
3478                     //  current delete, send a Delete request
3479                     //
3480                     if ((tableValue.providers[providerIndex].classList.size()
3481                             == 1) &&
3482                         (tableValue.providers[providerIndex].classList[0].equal(
3483                             className)))
3484                     {
3485                         _sendWaitDeleteRequests (indicationProviders,
3486                             sourceNameSpace,
3487                             formerSubscriptions[i],
3488                             acceptLangs,
3489                             contentLangs,
3490                             creator);
3491
3492                         //
3493                         //
3494                         //
3495                         _subscriptionTable->updateProviders
3496                             (instance.getPath (), indicationProvider, false);
3497                     }
3498
3499                     //
3500                     //  Otherwise, send a Modify request
3501                     //
3502                     else
3503                     {
3504                         Uint32 classIndex = _subscriptionTable->classInList
3505                             (className, tableValue.providers[providerIndex]);
3506                         if (classIndex != PEG_NOT_FOUND)
3507                         {
3508                             //
3509                             //  Send Modify requests
3510                             //
3511                             _sendWaitModifyRequests (indicationProviders,
3512                                 sourceNameSpace,
3513                                 requiredProperties, condition,
3514                                 query, queryLanguage,
3515                                 formerSubscriptions[i],
3516                                 acceptLangs,
3517                                 contentLangs,
3518                                 creator);
3519                         }
3520                         else
3521                         {
3522                             PEG_TRACE((TRC_INDICATION_SERVICE,Tracer::LEVEL1,
3523                                 "Class %s not found in tableValue.providers",
3524                                 (const char*)className.getString().getCString()
3525                                 ));
3526                         }
3527                     }
3528                 }
3529                 else
3530                 {
3531                     //
3532                     //  The subscription was not served by the provider
3533                     //
3534                 }
3535             }
3536             else
3537             {
3538                 //
3539                 //  Subscription not found in Active Subscriptions table
3540                 //
3541             }
3542         }
3543
3544 #if 0
3545         //
3546         //  Create NoProviderAlertIndication instance
3547         //  ATTN: NoProviderAlertIndication must be defined
3548         //
3549         CIMInstance indicationInstance = _createAlertInstance
3550             (_CLASS_NO_PROVIDER_ALERT, formerSubscriptions);
3551
3552         //
3553         //  Send NoProviderAlertIndication to each unique handler instance
3554         //
3555         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
3556             "Sending NoProvider Alert for %u subscriptions",
3557             formerSubscriptions.size ()));
3558         _sendAlerts (formerSubscriptions, indicationInstance);
3559 #endif
3560         //
3561         //  NOTE: When a provider that was previously serving a subscription
3562         //  no longer serves the subscription due to a provider registration
3563         //  change, a log message is sent, even if there are still other
3564         //  providers serving the subscription
3565         //
3566
3567         //
3568         //  Log a message for each subscription
3569         //
3570         CIMClass providerClass = _subscriptionRepository->getClass
3571             (PEGASUS_NAMESPACENAME_INTEROP, PEGASUS_CLASSNAME_PROVIDER,
3572              true, true, false, CIMPropertyList ());
3573         CIMInstance providerCopy = provider.clone ();
3574         CIMObjectPath path = providerCopy.buildPath (providerClass);
3575         providerCopy.setPath (path);
3576         String logString1 = getProviderLogString (providerCopy);
3577
3578         for (Uint32 j = 0; j < formerSubscriptions.size (); j++)
3579         {
3580             //
3581             //  Get Provider Name, Subscription Filter Name and Handler Name
3582             //
3583             String logString2 = _getSubscriptionLogString
3584                 (formerSubscriptions[j]);
3585
3586             Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
3587                 Logger::WARNING,
3588                 MessageLoaderParms(
3589                     _MSG_PROVIDER_NO_LONGER_SERVING_KEY,
3590                     _MSG_PROVIDER_NO_LONGER_SERVING, logString1, logString2,
3591                     formerSubscriptions[j].getPath().getNameSpace().
3592                         getString()));
3593         }
3594     }
3595
3596     //
3597     //  Send response
3598     //
3599     CIMResponseMessage * response = request->buildResponse ();
3600     _enqueueResponse (request, response);
3601
3602     PEG_METHOD_EXIT ();
3603 }
3604
3605 void IndicationService::_handleNotifyProviderTerminationRequest
3606     (const Message * message)
3607 {
3608     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
3609         "IndicationService::_handleNotifyProviderTermination");
3610
3611     Array<CIMInstance> providerSubscriptions;
3612     CIMInstance indicationInstance;
3613
3614     CIMNotifyProviderTerminationRequestMessage* request =
3615         (CIMNotifyProviderTerminationRequestMessage*) message;
3616
3617     Array<CIMInstance> providers = request->providers;
3618
3619     for (Uint32 i = 0; i < providers.size (); i++)
3620     {
3621 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
3622         _providerIndicationCountTable.removeEntry(providers[i]);
3623 #endif
3624
3625         //
3626         //  Get list of affected subscriptions
3627         //
3628         //  _subscriptionTable->reflectProviderDisable also updates the
3629         //  Active Subscriptions hash table, and implements each subscription's
3630         //  On Fatal Error policy, if necessary
3631         //
3632         providerSubscriptions.clear();
3633         providerSubscriptions = _subscriptionTable->reflectProviderDisable(
3634             providers[i]);
3635
3636         if (providerSubscriptions.size() > 0)
3637         {
3638             //
3639             //  NOTE: When a provider that was previously serving a subscription
3640             //  no longer serves the subscription due to a provider termination,
3641             //  an alert is always sent, even if there are still other providers
3642             //  serving the subscription
3643             //
3644
3645 #if 0
3646             //
3647             //  Create ProviderTerminatedAlertIndication instance
3648             //  ATTN: ProviderTerminatedAlertIndication must be defined
3649             //
3650             indicationInstance = _createAlertInstance
3651                 (_CLASS_PROVIDER_TERMINATED_ALERT, providerSubscriptions);
3652
3653             //
3654             //  Send ProviderTerminatedAlertIndication to each unique handler
3655             //  instance
3656             //
3657             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
3658                 "Sending ProviderDisabled Alert for %u subscriptions",
3659                 providerSubscriptions.size ()));
3660             _sendAlerts (providerSubscriptions, indicationInstance);
3661 #endif
3662             //
3663             //  Log a message for each subscription
3664             //
3665             CIMClass providerClass = _subscriptionRepository->getClass(
3666                 PEGASUS_NAMESPACENAME_INTEROP, PEGASUS_CLASSNAME_PROVIDER,
3667                 true, true, false, CIMPropertyList());
3668             CIMInstance providerCopy = providers[i].clone();
3669             CIMObjectPath path = providerCopy.buildPath (providerClass);
3670             providerCopy.setPath (path);
3671             for (Uint32 j = 0; j < providerSubscriptions.size (); j++)
3672             {
3673                 //
3674                 //  Get Provider Name, Subscription Filter Name and Handler Name
3675                 //
3676                 String logString1 = getProviderLogString (providerCopy);
3677                 String logString2 = _getSubscriptionLogString
3678                     (providerSubscriptions[j]);
3679
3680                 Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
3681                     Logger::WARNING,
3682                     MessageLoaderParms(
3683                         _MSG_PROVIDER_NO_LONGER_SERVING_KEY,
3684                         _MSG_PROVIDER_NO_LONGER_SERVING, logString1, logString2,
3685                         providerSubscriptions[j].getPath().getNameSpace().
3686                             getString()));
3687             }
3688         }
3689     }
3690
3691     CIMResponseMessage * response = request->buildResponse ();
3692     _enqueueResponse (request, response);
3693
3694     PEG_METHOD_EXIT ();
3695 }
3696
3697 void IndicationService::_handleNotifyProviderEnableRequest
3698     (const Message * message)
3699 {
3700     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
3701         "IndicationService::_handleNotifyProviderEnableRequest");
3702
3703     CIMNotifyProviderEnableRequestMessage * request =
3704         (CIMNotifyProviderEnableRequestMessage *) message;
3705     ProviderIdContainer pidc = request->operationContext.get
3706         (ProviderIdContainer::NAME);
3707     CIMInstance providerModule = pidc.getModule();
3708     CIMInstance provider = pidc.getProvider();
3709 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
3710     Boolean isRemoteNameSpace = pidc.isRemoteNameSpace();
3711     String remoteInfo = pidc.getRemoteInfo();
3712 #endif
3713     Array<CIMInstance> capabilities = request->capInstances;
3714
3715     CIMException cimException;
3716     Array<CIMInstance> subscriptions;
3717     Array<ProviderClassList> indicationProviders;
3718
3719     //
3720     //  Get class name, namespace names, and property list
3721     //  from each capability instance
3722     //
3723     Uint32 numCapabilities = capabilities.size ();
3724     for (Uint32 i = 0; i < numCapabilities; i++)
3725     {
3726         CIMName className;
3727         Array<CIMNamespaceName> namespaceNames;
3728         CIMPropertyList propertyList;
3729         Array<CIMInstance> currentSubscriptions;
3730
3731         try
3732         {
3733             String cName;
3734             capabilities[i].getProperty (capabilities[i].findProperty
3735                 (_PROPERTY_CLASSNAME)).getValue ().get (cName);
3736             className = CIMName (cName);
3737
3738             Array<String> nsNames;
3739             capabilities[i].getProperty (capabilities[i].findProperty
3740                 (_PROPERTY_NAMESPACES)).getValue ().get (nsNames);
3741             for (Uint32 j = 0; j < nsNames.size (); j++)
3742             {
3743                 namespaceNames.append (CIMNamespaceName (nsNames[j]));
3744             }
3745
3746             Array<String> pNames;
3747             Array<CIMName> propertyNames;
3748             Uint32 propertiesIndex = capabilities[i].findProperty
3749                 (_PROPERTY_SUPPORTEDPROPERTIES);
3750             if (propertiesIndex != PEG_NOT_FOUND)
3751             {
3752                 CIMValue propertiesValue = capabilities[i].getProperty
3753                     (propertiesIndex).getValue ();
3754                 //
3755                 //  If the property list is not null, set the property names
3756                 //
3757                 if (!propertiesValue.isNull ())
3758                 {
3759                     propertiesValue.get (pNames);
3760                     for (Uint32 k = 0; k < pNames.size (); k++)
3761                     {
3762                         propertyNames.append (CIMName (pNames[k]));
3763                     }
3764                     propertyList.set (propertyNames);
3765                 }
3766             }
3767         }
3768         catch (Exception& exception)
3769         {
3770             //
3771             //  Error getting information from Capabilities instance
3772             //
3773             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL1,
3774                "Exception caught in handling provider enable notification: %s",
3775                 (const char*)exception.getMessage().getCString()));
3776
3777             cimException = CIMException(CIM_ERR_FAILED, exception.getMessage());
3778             break;
3779         }
3780         catch (...)
3781         {
3782             PEG_TRACE_CSTRING (TRC_INDICATION_SERVICE, Tracer::LEVEL1,
3783                "Error in handling provider enable notification");
3784
3785             cimException = PEGASUS_CIM_EXCEPTION_L(
3786                 CIM_ERR_FAILED,
3787                 MessageLoaderParms(
3788                     "IndicationService.IndicationService.UNKNOWN_ERROR",
3789                     "Unknown Error"));
3790             break;
3791         }
3792
3793         //
3794         //  Get matching subscriptions
3795         //
3796         currentSubscriptions = _getMatchingSubscriptions
3797             (className, namespaceNames, propertyList);
3798
3799         for (Uint32 c = 0; c < currentSubscriptions.size (); c++)
3800         {
3801             Boolean inList = false;
3802
3803             for (Uint32 m = 0; m < subscriptions.size (); m++)
3804             {
3805                 //
3806                 //  If the current subscription is already in the list of
3807                 //  matching subscriptions, add the current class to the
3808                 //  indication provider class list for the subscription
3809                 //
3810                 if (currentSubscriptions[c].identical (subscriptions[m]))
3811                 {
3812                     inList = true;
3813                     indicationProviders[m].classList.append (className);
3814                     break;
3815                 }
3816             }
3817
3818             if (!inList)
3819             {
3820                 //
3821                 //  If the current subscription is not already in the list of
3822                 //  matching subscriptions, add it to the list and add the
3823                 //  indication provider class list for the subscription
3824                 //
3825                 subscriptions.append (currentSubscriptions[c]);
3826                 ProviderClassList indicationProvider;
3827                 indicationProvider.provider = provider;
3828                 indicationProvider.providerModule = providerModule;
3829                 indicationProvider.classList.append (className);
3830 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
3831                 indicationProvider.isRemoteNameSpace = isRemoteNameSpace;
3832                 indicationProvider.remoteInfo = remoteInfo;
3833 #endif
3834                 indicationProviders.append (indicationProvider);
3835             }
3836         }
3837     }  //  for each capability instance
3838
3839     if (subscriptions.size () > 0)
3840     {
3841         CIMPropertyList requiredProperties;
3842         String condition;
3843         String query;
3844         String queryLanguage;
3845
3846         //
3847         //  Get Provider Name
3848         //
3849         String logString1 = getProviderLogString (provider);
3850
3851         for (Uint32 s = 0; s < subscriptions.size (); s++)
3852         {
3853             CIMNamespaceName sourceNameSpace;
3854             Array<CIMName> indicationSubclasses;
3855             CIMInstance instance = subscriptions[s];
3856             _getCreateParams (instance, indicationSubclasses,
3857                 requiredProperties, sourceNameSpace, condition, query,
3858                 queryLanguage);
3859
3860             //
3861             //  NOTE: These Create requests are not associated with a
3862             //  user request, so there is no associated authType or userName
3863             //  The Creator from the subscription instance is used for
3864             //  userName, and authType is not set
3865             //
3866             //  NOTE: the subscriptions in the subscriptions list came from
3867             //  the IndicationService's internal hash tables, and thus
3868             //  each instance is known to have a valid Creator property
3869             //
3870             String creator = instance.getProperty (instance.findProperty
3871                 (PEGASUS_PROPERTYNAME_INDSUB_CREATOR)).getValue
3872                 ().toString ();
3873
3874             AcceptLanguageList acceptLangs;
3875             Uint32 propIndex = instance.findProperty
3876                 (PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS);
3877             if (propIndex != PEG_NOT_FOUND)
3878             {
3879                 String acceptLangsString;
3880                 instance.getProperty(propIndex).getValue().get(
3881                     acceptLangsString);
3882                 if (acceptLangsString.size())
3883                 {
3884                     acceptLangs = LanguageParser::parseAcceptLanguageHeader(
3885                         acceptLangsString);
3886                 }
3887             }
3888             ContentLanguageList contentLangs;
3889             propIndex = instance.findProperty
3890                 (PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS);
3891             if (propIndex != PEG_NOT_FOUND)
3892             {
3893                 String contentLangsString;
3894                 instance.getProperty(propIndex).getValue().get(
3895                     contentLangsString);
3896                 if (contentLangsString.size())
3897                 {
3898                     contentLangs = LanguageParser::parseContentLanguageHeader(
3899                         contentLangsString);
3900                 }
3901             }
3902
3903             //
3904             //  Send Create requests
3905             //
3906             Array<ProviderClassList> currentIndicationProviders;
3907             currentIndicationProviders.append (indicationProviders[s]);
3908             Array<ProviderClassList> acceptedProviders;
3909             acceptedProviders = _sendWaitCreateRequests
3910                 (currentIndicationProviders,
3911                 sourceNameSpace, requiredProperties, condition,
3912                 query, queryLanguage, instance,
3913                 acceptLangs,
3914                 contentLangs,
3915                 creator);
3916
3917             if (acceptedProviders.size () > 0)
3918             {
3919                 //
3920                 //  Get Subscription entry from Active Subscriptions table
3921                 //
3922                 ActiveSubscriptionsTableEntry tableValue;
3923                 if (_subscriptionTable->getSubscriptionEntry
3924                     (instance.getPath (), tableValue))
3925                 {
3926                     //
3927                     //  Look for the provider in the subscription's list
3928                     //
3929                     Uint32 providerIndex =
3930                         _subscriptionTable->providerInList
3931                             (indicationProviders[s].provider, tableValue);
3932                     if (providerIndex != PEG_NOT_FOUND)
3933                     {
3934                         //
3935                         //  Provider is already in the list for this
3936                         //  subscription; add class to provider class list
3937                         //
3938                         for (Uint32 cn = 0;
3939                              cn < indicationProviders[s].classList.size ();
3940                              cn++)
3941                         {
3942                             _subscriptionTable->updateClasses
3943                                 (instance.getPath (),
3944                                 indicationProviders[s].provider,
3945                                 indicationProviders[s].classList[cn]);
3946                         }
3947                     }
3948                     else
3949                     {
3950                         //
3951                         //  Provider is not yet in the list for this
3952                         //  subscription; add provider to the list
3953                         //
3954                         _subscriptionTable->updateProviders
3955                             (instance.getPath (), indicationProviders[s],
3956                             true);
3957
3958                         //
3959                         //  NOTE: When a provider that was previously not
3960                         //  serving a subscription now serves the
3961                         //  subscription due to a provider being enabled, a
3962                         //  log message is sent, even if there were
3963                         //  previously other providers serving the
3964                         //  subscription
3965                         //
3966
3967                         //
3968                         //  Get Subscription Filter Name and Handler Name
3969                         //
3970                         String logString2 = _getSubscriptionLogString
3971                             (subscriptions[s]);
3972
3973                         //
3974                         //  Log a message for each subscription
3975                         //
3976                         Logger::put_l(Logger::STANDARD_LOG,
3977                             System::CIMSERVER, Logger::WARNING,
3978                             MessageLoaderParms(
3979                                 _MSG_PROVIDER_NOW_SERVING_KEY,
3980                                 _MSG_PROVIDER_NOW_SERVING,
3981                                 logString1, logString2,
3982                                 subscriptions[s].getPath().getNameSpace().
3983                                     getString()));
3984                     }
3985                 }
3986             }  //  if any provider accepted the create subscription request
3987         }  //  for each matching subscription
3988     }  //  if any matching subscriptions
3989
3990     //
3991     //  Send response
3992     //
3993     CIMResponseMessage * response = request->buildResponse ();
3994     response->cimException = cimException;
3995     _enqueueResponse (request, response);
3996
3997     PEG_METHOD_EXIT ();
3998 }
3999
4000 void IndicationService::_handleNotifyProviderFailRequest
4001     (Message * message)
4002 {
4003     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
4004         "IndicationService::_handleNotifyProviderFailRequest");
4005
4006     CIMNotifyProviderFailRequestMessage* request =
4007         dynamic_cast<CIMNotifyProviderFailRequestMessage*>(message);
4008     PEGASUS_ASSERT(request != 0);
4009
4010     String moduleName = request->moduleName;
4011     String userName = request->userName;
4012
4013     //
4014     //  Determine providers in module that were serving active subscriptions
4015     //  and update the Active Subscriptions Table
4016     //
4017     Array<ActiveSubscriptionsTableEntry> providerModuleSubscriptions =
4018         _subscriptionTable->reflectProviderModuleFailure
4019             (moduleName, userName, _authenticationEnabled);
4020
4021 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
4022     _providerIndicationCountTable.removeModuleEntries(moduleName);
4023 #endif
4024
4025     //
4026     //  FUTURE: Attempt to recreate the subscription state
4027     //
4028
4029     //
4030     //  Send response
4031     //
4032     CIMResponseMessage * response = request->buildResponse ();
4033     CIMNotifyProviderFailResponseMessage * failResponse =
4034         (CIMNotifyProviderFailResponseMessage *) response;
4035     failResponse->numSubscriptionsAffected =
4036         providerModuleSubscriptions.size ();
4037     _enqueueResponse (request, response);
4038 }
4039
4040 Boolean IndicationService::_canCreate (
4041     CIMInstance& instance,
4042     const CIMNamespaceName& nameSpace)
4043 {
4044     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "IndicationService::_canCreate");
4045
4046     // REVIEW: Derived classes of CIM_IndicationSubscription not
4047     // handled. It is reasonable for a user to derive from this
4048     // class and add extra properties.
4049
4050     // REVIEW: how does the provider manager know to forward
4051     // requests to this service? Is it by class name? If so,
4052     // shouldn't the provider use an is-a operator on the new
4053     // class?
4054
4055     //
4056     //  Validate that all properties in the instance are supported properties,
4057     //  and reject create if an unknown, unsupported property is found
4058     //
4059     _checkSupportedProperties (instance);
4060
4061     //
4062     //  Check all required properties exist
4063     //  For a property that has a default value, if it does not exist or is
4064     //  null, add or set property with default value
4065     //  For a property that has a specified set of valid values, validate
4066     //
4067     if ((instance.getClassName ().equal (PEGASUS_CLASSNAME_INDSUBSCRIPTION)) ||
4068         (instance.getClassName ().equal
4069             (PEGASUS_CLASSNAME_FORMATTEDINDSUBSCRIPTION)))
4070     {
4071         //
4072         //  Filter and Handler are key properties for Subscription
4073         //  No other properties are required
4074         //
4075         _checkRequiredProperty(
4076             instance,
4077             PEGASUS_PROPERTYNAME_FILTER,
4078             CIMTYPE_REFERENCE,
4079             true);
4080         _checkRequiredProperty(
4081             instance,
4082             PEGASUS_PROPERTYNAME_HANDLER,
4083             CIMTYPE_REFERENCE,
4084             true);
4085
4086         //
4087         //  Get filter and handler property values
4088         //
4089         CIMProperty filterProperty = instance.getProperty
4090             (instance.findProperty (PEGASUS_PROPERTYNAME_FILTER));
4091         CIMValue filterValue = filterProperty.getValue ();
4092         CIMObjectPath filterPath;
4093         filterValue.get (filterPath);
4094
4095         CIMProperty handlerProperty = instance.getProperty
4096             (instance.findProperty (PEGASUS_PROPERTYNAME_HANDLER));
4097         CIMValue handlerValue = handlerProperty.getValue ();
4098         CIMObjectPath handlerPath;
4099         handlerValue.get (handlerPath);
4100
4101         //
4102         //  Currently, the Indication Service requires that a Subscription
4103         //  instance and the Filter and Handler instances to which it refers
4104         //  all be created on the same Host.
4105         //  Developers are recommended NOT to include Host in the
4106         //  Filter or Handler reference property values.
4107         //
4108
4109         //
4110         //  If Host is included in a Filter or Handler reference property
4111         //  value, attempt to validate that it is correct.
4112         //  If Host cannot be validated, reject the create operation.
4113         //
4114         CIMObjectPath origFilterPath = filterPath;
4115         if (filterPath.getHost () != String::EMPTY)
4116         {
4117             if (!System::isLocalHost (filterPath.getHost()))
4118             {
4119                 //
4120                 //  Reject subscription creation
4121                 //
4122                 PEG_METHOD_EXIT();
4123                 throw PEGASUS_CIM_EXCEPTION_L(
4124                     CIM_ERR_INVALID_PARAMETER,
4125                     MessageLoaderParms(
4126                         _MSG_INVALID_VALUE_FOR_PROPERTY_KEY,
4127                         _MSG_INVALID_VALUE_FOR_PROPERTY,
4128                         origFilterPath.toString(),
4129                         PEGASUS_PROPERTYNAME_FILTER.getString()));
4130             }
4131         }
4132
4133         CIMObjectPath origHandlerPath = handlerPath;
4134         if (handlerPath.getHost () != String::EMPTY)
4135         {
4136             if (!System::isLocalHost (handlerPath.getHost()))
4137             {
4138                 //
4139                 //  Reject subscription creation
4140                 //
4141                 PEG_METHOD_EXIT();
4142                 throw PEGASUS_CIM_EXCEPTION_L(
4143                     CIM_ERR_INVALID_PARAMETER,
4144                     MessageLoaderParms(
4145                         _MSG_INVALID_VALUE_FOR_PROPERTY_KEY,
4146                         _MSG_INVALID_VALUE_FOR_PROPERTY,
4147                         origHandlerPath.toString(),
4148                         PEGASUS_PROPERTYNAME_HANDLER.getString()));
4149             }
4150         }
4151
4152         //
4153         //  Get Filter namespace - if not set in Filter reference property
4154         //  value, namespace is the namespace of the subscription
4155         //
4156         CIMNamespaceName filterNS = filterPath.getNameSpace ();
4157         if (filterNS.isNull ())
4158         {
4159             filterNS = nameSpace;
4160         }
4161
4162         //
4163         //  Get Handler namespace - if not set in Handler reference property
4164         //  value, namespace is the namespace of the subscription
4165         //
4166         CIMNamespaceName handlerNS = handlerPath.getNameSpace();
4167         if (handlerNS.isNull())
4168         {
4169             handlerNS = nameSpace;
4170         }
4171
4172         //
4173         //  Validate the Filter and Handler reference properties
4174         //  Ensure Filter and Handler instances can be retrieved from the
4175         //  repository
4176         //
4177         CIMInstance filterInstance =
4178             _subscriptionRepository->getInstance(filterNS, filterPath,
4179                 false, false, CIMPropertyList());
4180
4181         CIMInstance handlerInstance =
4182             _subscriptionRepository->getInstance(handlerNS, handlerPath,
4183                 false, false, CIMPropertyList());
4184
4185         //
4186         //  Set the key bindings in the subscription instance
4187         //
4188         Array<CIMKeyBinding> kb;
4189         kb.append(CIMKeyBinding(PEGASUS_PROPERTYNAME_FILTER, filterValue));
4190         kb.append(CIMKeyBinding(PEGASUS_PROPERTYNAME_HANDLER, handlerValue));
4191
4192         CIMObjectPath instanceRef = instance.getPath ();
4193         instanceRef.setKeyBindings(kb);
4194         instanceRef.setNameSpace(nameSpace);
4195         instance.setPath(instanceRef);
4196
4197         //
4198         //  Subscription State, Repeat Notification Policy, and On Fatal Error
4199         //  Policy properties each has a default value, a corresponding
4200         //  Other___ property, and a set of valid values
4201         //
4202         _checkPropertyWithOther(
4203             instance,
4204             PEGASUS_PROPERTYNAME_SUBSCRIPTION_STATE,
4205             _PROPERTY_OTHERSTATE,
4206             (Uint16) STATE_ENABLED,
4207             (Uint16) STATE_OTHER,
4208             _validStates,
4209             _supportedStates);
4210
4211         _checkPropertyWithOther(
4212             instance,
4213             _PROPERTY_REPEATNOTIFICATIONPOLICY,
4214             _PROPERTY_OTHERREPEATNOTIFICATIONPOLICY,
4215             (Uint16) _POLICY_NONE,
4216             (Uint16) _POLICY_OTHER,
4217             _validRepeatPolicies,
4218             _supportedRepeatPolicies);
4219
4220         _checkPropertyWithOther(
4221             instance,
4222             _PROPERTY_ONFATALERRORPOLICY,
4223             _PROPERTY_OTHERONFATALERRORPOLICY,
4224             (Uint16) _ERRORPOLICY_IGNORE,
4225             (Uint16) _ERRORPOLICY_OTHER,
4226             _validErrorPolicies,
4227             _supportedErrorPolicies);
4228
4229         //
4230         //  For each remaining property, verify that if the property exists in
4231         //  the instance it is of the correct type
4232         //
4233         _checkProperty(instance, _PROPERTY_FAILURETRIGGERTIMEINTERVAL,
4234             CIMTYPE_UINT64);
4235         _checkProperty(instance, _PROPERTY_LASTCHANGE, CIMTYPE_DATETIME);
4236         _checkProperty(instance, _PROPERTY_DURATION, CIMTYPE_UINT64);
4237         _checkProperty(instance, _PROPERTY_STARTTIME, CIMTYPE_DATETIME);
4238         _checkProperty(instance, _PROPERTY_TIMEREMAINING, CIMTYPE_UINT64);
4239         _checkProperty(instance, _PROPERTY_REPEATNOTIFICATIONINTERVAL,
4240             CIMTYPE_UINT64);
4241         _checkProperty(instance, _PROPERTY_REPEATNOTIFICATIONGAP,
4242             CIMTYPE_UINT64);
4243         _checkProperty(instance, _PROPERTY_REPEATNOTIFICATIONCOUNT,
4244             CIMTYPE_UINT16);
4245
4246         if (instance.getClassName().equal(
4247             PEGASUS_CLASSNAME_FORMATTEDINDSUBSCRIPTION))
4248         {
4249             Array<String> textFormatParams;
4250             CIMValue textFormatParamsValue;
4251             CIMClass indicationClass;
4252
4253             // get TextFormatParameters from instance
4254             Uint32 textFormatParamsPos =
4255             instance.findProperty(_PROPERTY_TEXTFORMATPARAMETERS);
4256
4257             if (textFormatParamsPos != PEG_NOT_FOUND)
4258             {
4259                 textFormatParamsValue = instance.getProperty(
4260                     textFormatParamsPos).getValue();
4261
4262                 if (!textFormatParamsValue.isNull())
4263                 {
4264                     textFormatParamsValue.get(textFormatParams);
4265                 }
4266             }
4267
4268             // get indication class
4269             indicationClass = _getIndicationClass (instance);
4270
4271             String textFormatStr;
4272             CIMValue textFormatValue;
4273
4274             // get TextFormatStr from instance
4275             Uint32 textFormatPos =
4276             instance.findProperty(_PROPERTY_TEXTFORMAT);
4277
4278             if (textFormatPos != PEG_NOT_FOUND)
4279             {
4280                 textFormatValue = instance.getProperty(
4281                     textFormatPos).getValue();
4282
4283 #if defined(PEGASUS_ENABLE_SYSTEM_LOG_HANDLER) || \
4284     defined(PEGASUS_ENABLE_EMAIL_HANDLER)
4285                 // if the value of textFormat is not null
4286                 if (!(textFormatValue.isNull()) &&
4287                     (textFormatValue.getType() == CIMTYPE_STRING) &&
4288                     !(textFormatValue.isArray()))
4289                 {
4290                     textFormatValue.get(textFormatStr);
4291
4292                     // Validates the syntax and the provided type for the
4293                     // property TextFormat
4294                     IndicationFormatter::validateTextFormat (
4295                         textFormatStr, indicationClass,
4296                         textFormatParams);
4297
4298                     // Validates the property names in TextFormatParameters
4299                     CIMNamespaceName sourceNameSpace;
4300                     String query;
4301                     String queryLanguage;
4302                     String filterName;
4303                     CIMPropertyList propertyList;
4304
4305                     //  Get filter properties
4306                     _subscriptionRepository->getFilterProperties (instance,
4307                         query, sourceNameSpace, queryLanguage, filterName);
4308
4309                     //  Build the query expression from the filter query
4310                     QueryExpression queryExpression = _getQueryExpression(query,
4311                         queryLanguage, sourceNameSpace);
4312
4313                     // the select clause projection
4314                     propertyList = queryExpression.getPropertyList();
4315
4316                     IndicationFormatter::validateTextFormatParameters(
4317                     propertyList, indicationClass, textFormatParams);
4318                 }
4319 #endif
4320             }
4321         }
4322     }
4323     else  // Filter or Handler
4324     {
4325         //
4326         //  Name, CreationClassName, SystemName, and SystemCreationClassName
4327         //  are key properties for Filter and Handler
4328         //  Name must exist
4329         //  If others do not exist, add and set to default
4330         //  If they exist but are NULL, set value to the default
4331         //  If they exist and are not NULL, validate the value
4332         //
4333
4334         if (instance.getClassName ().equal (PEGASUS_CLASSNAME_INDFILTER))
4335         {
4336             _checkRequiredProperty(
4337                 instance,
4338                 PEGASUS_PROPERTYNAME_NAME,
4339                 CIMTYPE_STRING,
4340                 true);
4341         }
4342         else
4343         {
4344 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
4345             // Name is an optional property for Handler. If Name key property
4346             // not found then set the Name value using GUID.
4347             _checkPropertyWithGuid(
4348                 instance,
4349                 PEGASUS_PROPERTYNAME_NAME);
4350 #else
4351             _checkRequiredProperty(
4352                 instance,
4353                 PEGASUS_PROPERTYNAME_NAME,
4354                 CIMTYPE_STRING,
4355                 true);
4356 #endif
4357         }
4358
4359         _initOrValidateStringProperty(
4360             instance,
4361             PEGASUS_PROPERTYNAME_CREATIONCLASSNAME,
4362             instance.getClassName().getString());
4363
4364         _initOrValidateStringProperty(
4365             instance,
4366             _PROPERTY_SYSTEMNAME,
4367             System::getFullyQualifiedHostName());
4368
4369         _initOrValidateStringProperty(
4370             instance,
4371             _PROPERTY_SYSTEMCREATIONCLASSNAME,
4372             System::getSystemCreationClassName());
4373
4374         if (instance.getClassName ().equal (PEGASUS_CLASSNAME_INDFILTER))
4375         {
4376             //
4377             //  Query and QueryLanguage properties are required for Filter
4378             //
4379             _checkRequiredProperty(
4380                 instance,
4381                 PEGASUS_PROPERTYNAME_QUERY,
4382                 CIMTYPE_STRING,
4383                 false);
4384             _checkRequiredProperty(
4385                 instance,
4386                 PEGASUS_PROPERTYNAME_QUERYLANGUAGE,
4387                 CIMTYPE_STRING,
4388                 false);
4389
4390             //
4391             //  Validate the query language is supported
4392             //
4393             String queryLanguage;
4394             instance.getProperty(
4395                 instance.findProperty(PEGASUS_PROPERTYNAME_QUERYLANGUAGE)).
4396                     getValue().get(queryLanguage);
4397
4398 #ifndef PEGASUS_ENABLE_CQL
4399             // Special code to block CQL, if CQL is disabled
4400             if ((queryLanguage == "CIM:CQL") || (queryLanguage == "DMTF:CQL"))
4401             {
4402                 // CQL is not allowed in this case
4403                 PEG_METHOD_EXIT();
4404                 throw PEGASUS_CIM_EXCEPTION(
4405                     CIM_ERR_NOT_SUPPORTED, queryLanguage);
4406             }
4407 #endif
4408
4409             //
4410             //  Default value for Source Namespace is the namespace of the
4411             //  Filter registration
4412             //
4413             CIMNamespaceName sourceNameSpace = CIMNamespaceName(
4414                 _checkPropertyWithDefault(
4415                     instance,
4416                     _PROPERTY_SOURCENAMESPACE,
4417                     nameSpace.getString()));
4418
4419             //
4420             //  Validate the query and indication class name
4421             //  An exception is thrown if the query is invalid or the class
4422             //  is not an indication class
4423             //
4424             String filterQuery = instance.getProperty (instance.findProperty
4425                 (PEGASUS_PROPERTYNAME_QUERY)).getValue ().toString ();
4426
4427             QueryExpression queryExpression;
4428             try
4429             {
4430                 queryExpression = _getQueryExpression(
4431                     filterQuery, queryLanguage, sourceNameSpace);
4432             }
4433             catch (QueryLanguageInvalidException&)
4434             {
4435                 // The filter query had an invalid language name.
4436                 PEG_METHOD_EXIT();
4437                 throw PEGASUS_CIM_EXCEPTION(
4438                     CIM_ERR_NOT_SUPPORTED, queryLanguage);
4439             }
4440
4441             CIMName indicationClassName = _getIndicationClassName
4442                 (queryExpression, sourceNameSpace);
4443
4444             //
4445             // Make sure that the FROM class exists in the repository.
4446             //
4447             CIMClass indicationClass = _subscriptionRepository->getClass
4448                 (sourceNameSpace, indicationClassName,
4449                 false, false, false, CIMPropertyList ());
4450
4451             //
4452             // Validate all the properties in the SELECT statement exist
4453             // on their class context.
4454             //
4455             try
4456             {
4457               queryExpression.validate();
4458             }
4459             catch (QueryMissingPropertyException& qmp)
4460             {
4461               // A property does not exist on the class it is scoped to.
4462               PEG_METHOD_EXIT();
4463               throw PEGASUS_CIM_EXCEPTION
4464                 (CIM_ERR_INVALID_PARAMETER, qmp.getMessage());
4465             }
4466             catch (QueryValidationException& qv)
4467             {
4468               // Received some other validation error.
4469               // This includes detecting an array property
4470               // is in the WHERE list for WQL.
4471               PEG_METHOD_EXIT();
4472               throw PEGASUS_CIM_EXCEPTION
4473                 (CIM_ERR_NOT_SUPPORTED, qv.getMessage());
4474             }
4475         }
4476
4477         //
4478         //  Currently only five subclasses of the Listener Destination
4479         //  class are supported -- further subclassing is not currently
4480         //  supported
4481         //
4482         else if ((instance.getClassName ().equal
4483                   (PEGASUS_CLASSNAME_INDHANDLER_CIMXML)) ||
4484                  (instance.getClassName ().equal
4485                   (PEGASUS_CLASSNAME_LSTNRDST_CIMXML)) ||
4486          (instance.getClassName ().equal
4487           (PEGASUS_CLASSNAME_LSTNRDST_SYSTEM_LOG)) ||
4488          (instance.getClassName ().equal
4489           (PEGASUS_CLASSNAME_LSTNRDST_EMAIL)) ||
4490                  (instance.getClassName ().equal
4491                   (PEGASUS_CLASSNAME_INDHANDLER_SNMP)))
4492         {
4493 #ifndef PEGASUS_ENABLE_SYSTEM_LOG_HANDLER
4494             if (instance.getClassName ().equal
4495             (PEGASUS_CLASSNAME_LSTNRDST_SYSTEM_LOG))
4496             {
4497                 //
4498                 //  The System Log Handler is not enabled currently,
4499                 //  this class is not currently served by the Indication Service
4500                 //
4501                 PEG_METHOD_EXIT ();
4502
4503                 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_NOT_SUPPORTED,
4504                 MessageLoaderParms(_MSG_CLASS_NOT_SERVED_KEY,
4505             _MSG_CLASS_NOT_SERVED));
4506         }
4507 #endif
4508
4509 #if !defined(PEGASUS_ENABLE_EMAIL_HANDLER)
4510
4511             if (instance.getClassName ().equal
4512             (PEGASUS_CLASSNAME_LSTNRDST_EMAIL))
4513             {
4514                 //
4515                 //  The Email Handler is not enabled currently,
4516                 //  this class is not currently served by the Indication Service
4517                 //
4518                 PEG_METHOD_EXIT ();
4519
4520                 throw PEGASUS_CIM_EXCEPTION_L (CIM_ERR_NOT_SUPPORTED,
4521                 MessageLoaderParms(_MSG_CLASS_NOT_SERVED_KEY,
4522                    _MSG_CLASS_NOT_SERVED));
4523         }
4524 #endif
4525             _checkPropertyWithOther(
4526                 instance,
4527                 PEGASUS_PROPERTYNAME_PERSISTENCETYPE,
4528                 _PROPERTY_OTHERPERSISTENCETYPE,
4529                 (Uint16) PERSISTENCE_PERMANENT,
4530                 (Uint16) PERSISTENCE_OTHER,
4531                 _validPersistenceTypes,
4532                 _supportedPersistenceTypes);
4533
4534             //
4535             //  For remaining property, verify that if the property exists in
4536             //  the instance it is of the correct type
4537             //
4538             _checkProperty(instance, _PROPERTY_OWNER, CIMTYPE_STRING);
4539
4540             if (instance.getClassName().equal(
4541                     PEGASUS_CLASSNAME_INDHANDLER_CIMXML) ||
4542                 instance.getClassName().equal(
4543                     PEGASUS_CLASSNAME_LSTNRDST_CIMXML))
4544             {
4545                 //
4546                 //  Destination property is required for CIMXML
4547                 //  Handler subclass
4548                 //
4549                 _checkRequiredProperty(
4550                     instance,
4551                     PEGASUS_PROPERTYNAME_LSTNRDST_DESTINATION,
4552                     CIMTYPE_STRING,
4553                     false);
4554             }
4555
4556             if (instance.getClassName().equal
4557                 (PEGASUS_CLASSNAME_INDHANDLER_SNMP))
4558             {
4559                 //
4560                 //  TargetHost property is required for SNMP
4561                 //  Handler subclass
4562                 //
4563                 _checkRequiredProperty(
4564                     instance,
4565                     PEGASUS_PROPERTYNAME_LSTNRDST_TARGETHOST,
4566                     CIMTYPE_STRING,
4567                     false);
4568
4569                 //
4570                 //  TargetHostFormat property is required for SNMP
4571                 //  Handler subclass
4572                 //
4573                 _checkRequiredProperty(
4574                     instance,
4575                     _PROPERTY_TARGETHOSTFORMAT,
4576                     CIMTYPE_UINT16,
4577                     false);
4578
4579                 //
4580                 //  SNMPVersion property is required for SNMP Handler
4581                 //
4582                 _checkRequiredProperty(
4583                     instance,
4584                     PEGASUS_PROPERTYNAME_SNMPVERSION,
4585                     CIMTYPE_UINT16,
4586                     false);
4587
4588                 // Currently, only SNMPv1 trap and SNMPv2C trap are supported,
4589                 // verify if the value of SNMPVersion is one of them
4590
4591                 _checkValue(
4592                     instance,
4593                     PEGASUS_PROPERTYNAME_SNMPVERSION,
4594                     _validSNMPVersion,
4595                     _supportedSNMPVersion);
4596
4597                 //
4598                 //  For each remaining property, verify that if the property
4599                 //  exists in the instance it is of the correct type
4600                 //
4601                 _checkProperty(instance, _PROPERTY_PORTNUMBER, CIMTYPE_UINT32);
4602                 _checkProperty(instance, _PROPERTY_SNMPSECURITYNAME,
4603                     CIMTYPE_STRING);
4604                 _checkProperty(instance, _PROPERTY_SNMPENGINEID,
4605                     CIMTYPE_STRING);
4606             }
4607
4608             if (instance.getClassName().equal
4609                 (PEGASUS_CLASSNAME_LSTNRDST_EMAIL))
4610             {
4611                 //
4612                 //  MailTo property is required for Email
4613                 //  Handler subclass
4614                 //
4615                 _checkRequiredProperty(
4616                     instance,
4617                     PEGASUS_PROPERTYNAME_LSTNRDST_MAILTO,
4618                     CIMTYPE_STRING,
4619                     false,
4620                     true);
4621
4622                 // get MailTo from handler instance
4623                 Array<String> mailTo;
4624                 instance.getProperty(instance.findProperty(
4625                     PEGASUS_PROPERTYNAME_LSTNRDST_MAILTO)).getValue().get(
4626                         mailTo);
4627
4628                 // Build mail address string
4629                 String mailAddrStr;
4630                 Uint32 mailAddrSize = mailTo.size();
4631
4632                 for (Uint32 i=0; i < mailAddrSize; i++)
4633                 {
4634                     mailAddrStr.append(mailTo[i]);
4635
4636                     if (i < (mailAddrSize - 1))
4637                     {
4638                         mailAddrStr.append(",");
4639                     }
4640                 }
4641
4642
4643                 //
4644                 // Email address can not be an empty string
4645                 //
4646                 if (mailAddrStr == String::EMPTY)
4647                 {
4648                     PEG_METHOD_EXIT();
4649                     throw PEGASUS_CIM_EXCEPTION_L(
4650                         CIM_ERR_FAILED,
4651                         MessageLoaderParms(
4652                             "IndicationService.IndicationService."
4653                                 "_MSG_DO_NOT_HAVE_EMAIL_ADDRESS",
4654                             "Do not have an e-mail address."));
4655                 }
4656
4657                 //
4658                 //  MailSubject property is required for Email
4659                 //  Handler subclass
4660                 //
4661                 _checkRequiredProperty(
4662                     instance,
4663                     PEGASUS_PROPERTYNAME_LSTNRDST_MAILSUBJECT,
4664                     CIMTYPE_STRING,
4665                     false);
4666
4667                 //
4668                 //  For MailCc property, verify that if the property
4669                 //  exists in the instance it is of the correct type
4670                 //
4671                 _checkProperty(
4672                     instance,
4673                     PEGASUS_PROPERTYNAME_LSTNRDST_MAILCC,
4674                     CIMTYPE_STRING,
4675                     true);
4676             }
4677         }
4678
4679         else
4680         {
4681             //
4682             //  A class not currently served by the Indication Service
4683             //
4684             PEG_METHOD_EXIT();
4685
4686             throw PEGASUS_CIM_EXCEPTION_L(
4687                 CIM_ERR_NOT_SUPPORTED,
4688                 MessageLoaderParms(
4689                     _MSG_CLASS_NOT_SERVED_KEY,
4690                     _MSG_CLASS_NOT_SERVED));
4691         }
4692     }
4693
4694     PEG_METHOD_EXIT();
4695     return true;
4696 }
4697
4698 void IndicationService::_checkRequiredProperty(
4699     CIMInstance& instance,
4700     const CIMName& propertyName,
4701     const CIMType expectedType,
4702     Boolean isKeyProperty,
4703     Boolean isArray)
4704 {
4705     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
4706         "IndicationService::_checkRequiredProperty");
4707
4708     Boolean missingProperty = false;
4709
4710     //
4711     //  Required property must exist in instance
4712     //
4713     if (instance.findProperty (propertyName) == PEG_NOT_FOUND)
4714     {
4715         missingProperty = true;
4716     }
4717     else
4718     {
4719         //
4720         //  Get the property
4721         //
4722         CIMProperty theProperty = instance.getProperty
4723             (instance.findProperty (propertyName));
4724         CIMValue theValue = theProperty.getValue ();
4725
4726         //
4727         //  Required property must have a non-null value
4728         //
4729         if (theValue.isNull ())
4730         {
4731             missingProperty = true;
4732         }
4733         else
4734         {
4735             //
4736             //  Check that the property value is of the correct type
4737             //
4738             if ((theValue.getType () != expectedType) ||
4739                 (theValue.isArray () != isArray))
4740             {
4741                 if (theValue.isArray ())
4742                 {
4743                     PEG_METHOD_EXIT();
4744                     throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_INVALID_PARAMETER,
4745                         MessageLoaderParms(
4746                             _MSG_INVALID_TYPE_ARRAY_OF_FOR_PROPERTY_KEY,
4747                             _MSG_INVALID_TYPE_ARRAY_OF_FOR_PROPERTY,
4748                             cimTypeToString(theValue.getType()),
4749                             propertyName.getString()));
4750                 }
4751                 else
4752                 {
4753                     PEG_METHOD_EXIT();
4754                     throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_INVALID_PARAMETER,
4755                         MessageLoaderParms(
4756                             _MSG_INVALID_TYPE_FOR_PROPERTY_KEY,
4757                             _MSG_INVALID_TYPE_FOR_PROPERTY,
4758                             cimTypeToString(theValue.getType()),
4759                             propertyName.getString()));
4760                 }
4761             }
4762         }
4763     }
4764
4765     if (missingProperty)
4766     {
4767         if (isKeyProperty)
4768         {
4769             PEG_METHOD_EXIT();
4770             throw PEGASUS_CIM_EXCEPTION_L(
4771                 CIM_ERR_INVALID_PARAMETER,
4772                 MessageLoaderParms(
4773                     "IndicationService.IndicationService._MSG_KEY_PROPERTY",
4774                     "The key property $0 is missing.",
4775                     propertyName.getString()));
4776         }
4777         else
4778         {
4779             PEG_METHOD_EXIT();
4780             throw PEGASUS_CIM_EXCEPTION_L(
4781                 CIM_ERR_INVALID_PARAMETER,
4782                 MessageLoaderParms(
4783                     _MSG_PROPERTY_KEY,
4784                     _MSG_PROPERTY,
4785                     propertyName.getString()));
4786         }
4787     }
4788
4789     PEG_METHOD_EXIT ();
4790 }
4791
4792 void IndicationService::_checkPropertyWithOther (
4793     CIMInstance& instance,
4794     const CIMName& propertyName,
4795     const CIMName& otherPropertyName,
4796     const Uint16 defaultValue,
4797     const Uint16 otherValue,
4798     const Array<Uint16>& validValues,
4799     const Array<Uint16>& supportedValues)
4800 {
4801     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
4802         "IndicationService::_checkPropertyWithOther");
4803
4804     Uint16 result = defaultValue;
4805
4806     //
4807     //  If the property doesn't exist, add it with the default value
4808     //
4809     if (instance.findProperty (propertyName) == PEG_NOT_FOUND)
4810     {
4811         instance.addProperty (CIMProperty (propertyName,
4812             CIMValue (defaultValue)));
4813     }
4814     else
4815     {
4816         //
4817         //  Get the property
4818         //
4819         CIMProperty theProperty = instance.getProperty
4820             (instance.findProperty (propertyName));
4821         CIMValue theValue = theProperty.getValue ();
4822
4823         //
4824         //  Check that the value is of the correct type
4825         //
4826         if ((theValue.getType () != CIMTYPE_UINT16) || (theValue.isArray ()))
4827         {
4828             String exceptionStr;
4829             if (theValue.isArray ())
4830             {
4831                 MessageLoaderParms parms(
4832                     "IndicationService.IndicationService."
4833                         "_MSG_INVALID_TYPE_ARRAY_OF_FOR_PROPERTY",
4834                     "Invalid type array of $0 for property $1",
4835                     cimTypeToString(theValue.getType()),
4836                     propertyName.getString());
4837
4838                 exceptionStr.append(MessageLoader::getMessage(parms));
4839             }
4840             else
4841             {
4842                 MessageLoaderParms parms(
4843                     "IndicationService.IndicationService."
4844                         "_MSG_INVALID_TYPE_FOR_PROPERTY",
4845                     "Invalid type $0 for property $1",
4846                     cimTypeToString(theValue.getType()),
4847                     propertyName.getString());
4848
4849                 exceptionStr.append(MessageLoader::getMessage(parms));
4850             }
4851             PEG_METHOD_EXIT ();
4852             throw PEGASUS_CIM_EXCEPTION (CIM_ERR_INVALID_PARAMETER,
4853                 exceptionStr);
4854         }
4855
4856         //
4857         //  If the value is null, set to the default value
4858         //
4859         if (theValue.isNull ())
4860         {
4861             theProperty.setValue (CIMValue (defaultValue));
4862         }
4863         else
4864         {
4865             theValue.get (result);
4866
4867             //
4868             //  Validate the value
4869             //
4870             //  Note: Valid values are defined by the CIM Event Schema MOF
4871             //
4872             if (!Contains (validValues, result))
4873             {
4874                 PEG_METHOD_EXIT();
4875                 throw PEGASUS_CIM_EXCEPTION_L(
4876                     CIM_ERR_INVALID_PARAMETER,
4877                     MessageLoaderParms(
4878                         _MSG_INVALID_VALUE_FOR_PROPERTY_KEY,
4879                         _MSG_INVALID_VALUE_FOR_PROPERTY,
4880                         theValue.toString(),
4881                         propertyName.getString()));
4882             }
4883
4884             //
4885             //  Check for valid values that are not supported
4886             //
4887             //  Note: Supported values are a subset of the valid values
4888             //  Some valid values, as defined in the MOF, are not currently
4889             //  supported by the Pegasus IndicationService
4890             //
4891             if (!Contains(supportedValues, result))
4892             {
4893                 PEG_METHOD_EXIT();
4894                 throw PEGASUS_CIM_EXCEPTION_L(
4895                     CIM_ERR_NOT_SUPPORTED,
4896                     MessageLoaderParms(
4897                         _MSG_UNSUPPORTED_VALUE_FOR_PROPERTY_KEY,
4898                         _MSG_UNSUPPORTED_VALUE_FOR_PROPERTY,
4899                         theValue.toString(),
4900                         propertyName.getString()));
4901             }
4902         }
4903
4904         //
4905         //  If the value is Other, the Other
4906         //  property must exist, value must not be NULL and type must be String
4907         //
4908         if (result == otherValue)
4909         {
4910             if (instance.findProperty(otherPropertyName) == PEG_NOT_FOUND)
4911             {
4912                 PEG_METHOD_EXIT();
4913                 throw PEGASUS_CIM_EXCEPTION_L(
4914                     CIM_ERR_INVALID_PARAMETER,
4915                     MessageLoaderParms(
4916                         _MSG_PROPERTY_KEY,
4917                         _MSG_PROPERTY,
4918                         otherPropertyName.getString()));
4919             }
4920             else
4921             {
4922                 CIMProperty otherProperty = instance.getProperty
4923                     (instance.findProperty(otherPropertyName));
4924                 CIMValue theOtherValue = otherProperty.getValue();
4925                 if (theOtherValue.isNull())
4926                 {
4927                     PEG_METHOD_EXIT();
4928                     throw PEGASUS_CIM_EXCEPTION_L(
4929                         CIM_ERR_INVALID_PARAMETER,
4930                         MessageLoaderParms(
4931                             _MSG_PROPERTY_KEY,
4932                             _MSG_PROPERTY,
4933                             otherPropertyName.getString()));
4934                 }
4935                 else if (theOtherValue.getType() != CIMTYPE_STRING)
4936                 {
4937                     //
4938                     //  Property exists and is not null,
4939                     //  but is not of correct type
4940                     //
4941                     PEG_METHOD_EXIT();
4942                     throw PEGASUS_CIM_EXCEPTION_L(
4943                         CIM_ERR_INVALID_PARAMETER,
4944                         MessageLoaderParms(
4945                             _MSG_INVALID_TYPE_FOR_PROPERTY_KEY,
4946                             _MSG_INVALID_TYPE_FOR_PROPERTY,
4947                             cimTypeToString(theOtherValue.getType()),
4948                             otherPropertyName.getString()));
4949                 }
4950             }
4951         }
4952
4953         //
4954         //  If value is not Other, Other property must not exist
4955         //  or must be NULL
4956         //
4957         else if (instance.findProperty (otherPropertyName) != PEG_NOT_FOUND)
4958         {
4959             CIMProperty otherProperty = instance.getProperty(
4960                 instance.findProperty(otherPropertyName));
4961             CIMValue theOtherValue = otherProperty.getValue();
4962             if (!theOtherValue.isNull())
4963             {
4964                 PEG_METHOD_EXIT();
4965                 throw PEGASUS_CIM_EXCEPTION_L(
4966                     CIM_ERR_INVALID_PARAMETER,
4967                     MessageLoaderParms(
4968                         "IndicationService.IndicationService."
4969                             "_MSG_PROPERTY_PRESENT_BUT_VALUE_NOT",
4970                         "The $0 property is present, but the $1 value is "
4971                             "not $2.",
4972                         otherPropertyName.getString(),
4973                         propertyName.getString(),
4974                         CIMValue(otherValue).toString()));
4975             }
4976         }
4977     }
4978
4979     PEG_METHOD_EXIT();
4980 }
4981
4982 String IndicationService::_checkPropertyWithGuid(
4983     CIMInstance& instance,
4984     const CIMName& propertyName)
4985 {
4986     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
4987         "IndicationService::_checkPropertyWithGuid");
4988
4989    String value = _checkPropertyWithDefault(
4990        instance,
4991        propertyName,
4992        Guid::getGuid(PEGASUS_INSTANCEID_GLOBAL_PREFIX));
4993
4994    PEG_METHOD_EXIT();
4995
4996    return value;
4997 }
4998
4999 String IndicationService::_checkPropertyWithDefault(
5000     CIMInstance& instance,
5001     const CIMName& propertyName,
5002     const String& defaultValue)
5003 {
5004     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
5005         "IndicationService::_checkPropertyWithDefault");
5006
5007     String result = defaultValue;
5008
5009     //
5010     //  If the property doesn't exist, add it with the default value
5011     //
5012     if (instance.findProperty (propertyName) == PEG_NOT_FOUND)
5013     {
5014         instance.addProperty (CIMProperty (propertyName,
5015             CIMValue (defaultValue)));
5016     }
5017     else
5018     {
5019         //
5020         //  Get the property
5021         //
5022         CIMProperty theProperty = instance.getProperty
5023             (instance.findProperty (propertyName));
5024         CIMValue theValue = theProperty.getValue ();
5025
5026         //
5027         //  If the value is null, set to the default value
5028         //
5029         if (theValue.isNull ())
5030         {
5031             theProperty.setValue (CIMValue (defaultValue));
5032         }
5033         else if ((theValue.getType () != CIMTYPE_STRING) ||
5034                  (theValue.isArray ()))
5035         {
5036             //
5037             //  Property exists and is not null,
5038             //  but is not of correct type
5039             //
5040             if (theValue.isArray ())
5041             {
5042                 PEG_METHOD_EXIT();
5043                 throw PEGASUS_CIM_EXCEPTION_L(
5044                     CIM_ERR_INVALID_PARAMETER,
5045                     MessageLoaderParms(
5046                         _MSG_INVALID_TYPE_ARRAY_OF_FOR_PROPERTY_KEY,
5047                         _MSG_INVALID_TYPE_ARRAY_OF_FOR_PROPERTY,
5048                         cimTypeToString(theValue.getType()),
5049                         propertyName.getString()));
5050             }
5051             else
5052             {
5053                 PEG_METHOD_EXIT();
5054                 throw PEGASUS_CIM_EXCEPTION_L(
5055                     CIM_ERR_INVALID_PARAMETER,
5056                     MessageLoaderParms(
5057                         _MSG_INVALID_TYPE_FOR_PROPERTY_KEY,
5058                         _MSG_INVALID_TYPE_FOR_PROPERTY,
5059                         cimTypeToString(theValue.getType()),
5060                         propertyName.getString()));
5061             }
5062         }
5063         else
5064         {
5065             theValue.get (result);
5066         }
5067     }
5068
5069     PEG_METHOD_EXIT ();
5070     return result;
5071 }
5072
5073 String IndicationService::_initOrValidateStringProperty (
5074     CIMInstance& instance,
5075     const CIMName& propertyName,
5076     const String& defaultValue)
5077 {
5078     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
5079         "IndicationService::_initOrValidateStringProperty");
5080
5081     String result = defaultValue;
5082
5083     String propertyValue = _checkPropertyWithDefault (instance, propertyName,
5084         defaultValue);
5085
5086     if (propertyValue != defaultValue)
5087     {
5088 #ifdef PEGASUS_SNIA_EXTENSIONS
5089         // SNIA requires SystemName and SystemCreationClassName to be
5090         // overridden with the correct values.
5091         if ((propertyName == _PROPERTY_SYSTEMNAME) ||
5092             (propertyName == _PROPERTY_SYSTEMCREATIONCLASSNAME))
5093         {
5094             // The property must exist after _checkPropertyWithDefault is called
5095             CIMProperty p =
5096                 instance.getProperty(instance.findProperty(propertyName));
5097             p.setValue(CIMValue(defaultValue));
5098             PEG_METHOD_EXIT();
5099             return result;
5100         }
5101 #endif
5102
5103         //
5104         //  Property value specified is invalid
5105         //
5106         PEG_METHOD_EXIT();
5107         throw PEGASUS_CIM_EXCEPTION_L(
5108             CIM_ERR_INVALID_PARAMETER,
5109             MessageLoaderParms(
5110                 _MSG_INVALID_VALUE_FOR_PROPERTY_KEY,
5111                 _MSG_INVALID_VALUE_FOR_PROPERTY,
5112                 propertyValue,
5113                 propertyName.getString()));
5114     }
5115
5116     PEG_METHOD_EXIT ();
5117     return result;
5118 }
5119
5120 void IndicationService::_checkProperty (
5121     CIMInstance& instance,
5122     const CIMName& propertyName,
5123     const CIMType expectedType,
5124     const Boolean isArray)
5125 {
5126     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
5127         "IndicationService::_checkProperty");
5128
5129     //
5130     //  If the property exists, get it
5131     //
5132     Uint32 propPos = instance.findProperty (propertyName);
5133     if (propPos != PEG_NOT_FOUND)
5134     {
5135         CIMProperty theProperty = instance.getProperty (propPos);
5136         CIMValue theValue = theProperty.getValue ();
5137
5138         //
5139         //  If the value is not null, check the type
5140         //
5141         if (!theValue.isNull ())
5142         {
5143             if ((theValue.getType () != expectedType) ||
5144                 (theValue.isArray () != isArray))
5145             {
5146                 //
5147                 //  Property exists and is not null, but is not of correct type
5148                 //
5149                 if (theValue.isArray ())
5150                 {
5151                     PEG_METHOD_EXIT();
5152                     throw PEGASUS_CIM_EXCEPTION_L(
5153                         CIM_ERR_INVALID_PARAMETER,
5154                         MessageLoaderParms(
5155                             _MSG_INVALID_TYPE_ARRAY_OF_FOR_PROPERTY_KEY,
5156                             _MSG_INVALID_TYPE_ARRAY_OF_FOR_PROPERTY,
5157                             cimTypeToString(theValue.getType()),
5158                             propertyName.getString()));
5159                 }
5160                 else
5161                 {
5162                     PEG_METHOD_EXIT();
5163                     throw PEGASUS_CIM_EXCEPTION_L(
5164                         CIM_ERR_INVALID_PARAMETER,
5165                         MessageLoaderParms(
5166                             _MSG_INVALID_TYPE_FOR_PROPERTY_KEY,
5167                             _MSG_INVALID_TYPE_FOR_PROPERTY,
5168                             cimTypeToString(theValue.getType()),
5169                             propertyName.getString()));
5170                 }
5171             }
5172         }
5173     }
5174
5175     PEG_METHOD_EXIT ();
5176 }
5177
5178 void IndicationService::_checkSupportedProperties (
5179     const CIMInstance& instance)
5180 {
5181     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
5182         "IndicationService::_checkSupportedProperties");
5183
5184     CIMName className = instance.getClassName ();
5185     Array<CIMName> emptyArray;
5186     Array<CIMName>& supportedProperties = emptyArray;
5187
5188     //
5189     //  Get list of supported properties for the class
5190     //
5191     if (className.equal (PEGASUS_CLASSNAME_INDSUBSCRIPTION))
5192     {
5193         supportedProperties = _supportedSubscriptionProperties;
5194     }
5195     else if (className.equal (PEGASUS_CLASSNAME_FORMATTEDINDSUBSCRIPTION))
5196     {
5197         supportedProperties = _supportedFormattedSubscriptionProperties;
5198     }
5199     else if (className.equal (PEGASUS_CLASSNAME_INDFILTER))
5200     {
5201         supportedProperties = _supportedFilterProperties;
5202     }
5203     else if (className.equal (PEGASUS_CLASSNAME_INDHANDLER_CIMXML))
5204     {
5205         supportedProperties = _supportedCIMXMLHandlerProperties;
5206     }
5207     else if (className.equal (PEGASUS_CLASSNAME_LSTNRDST_CIMXML))
5208     {
5209         supportedProperties = _supportedCIMXMLListenerDestinationProperties;
5210     }
5211     else if (className.equal (PEGASUS_CLASSNAME_INDHANDLER_SNMP))
5212     {
5213         supportedProperties = _supportedSNMPHandlerProperties;
5214     }
5215     else if (className.equal (PEGASUS_CLASSNAME_LSTNRDST_SYSTEM_LOG))
5216     {
5217         supportedProperties = _supportedSyslogListenerDestinationProperties;
5218     }
5219     else if (className.equal (PEGASUS_CLASSNAME_LSTNRDST_EMAIL))
5220     {
5221         supportedProperties = _supportedEmailListenerDestinationProperties;
5222     }
5223     else
5224     {
5225         PEGASUS_ASSERT (false);
5226     }
5227
5228     //
5229     //  Check if each property in the instance is in the list of supported,
5230     //  known properties for its class
5231     //
5232     for (Uint32 i = 0; i < instance.getPropertyCount (); i++)
5233     {
5234         if (!ContainsCIMName (supportedProperties,
5235             instance.getProperty (i).getName ()))
5236         {
5237             //
5238             //  Throw an exception if an unknown, unsupported property was found
5239             //
5240             PEG_METHOD_EXIT ();
5241             throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_NOT_SUPPORTED,
5242                 MessageLoaderParms(
5243                     "IndicationService.IndicationService."
5244                         "_MSG_PROPERTY_NOT_SUPPORTED",
5245                     "Property $0 is not supported in class $1",
5246                     instance.getProperty (i).getName ().getString (),
5247                     className.getString ()));
5248         }
5249     }
5250
5251     PEG_METHOD_EXIT ();
5252 }
5253
5254 void IndicationService::_checkValue (
5255     const CIMInstance& instance,
5256     const CIMName& propertyName,
5257     const Array<Uint16>& validValues,
5258     const Array<Uint16>& supportedValues)
5259 {
5260     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
5261         "IndicationService::_checkValue");
5262
5263     Uint16 theValue;
5264
5265     // get the property value
5266     Uint32 propPos = instance.findProperty (propertyName);
5267     if (propPos != PEG_NOT_FOUND)
5268     {
5269         CIMValue propertyValue = (instance.getProperty(propPos)).getValue();
5270
5271         if (!(propertyValue.isNull()))
5272         {
5273             propertyValue.get(theValue);
5274
5275             // Validate the value
5276             // Note: Valid values are defined by the PG Events MOF
5277             if (!Contains(validValues, theValue))
5278             {
5279                 PEG_METHOD_EXIT();
5280
5281                 throw PEGASUS_CIM_EXCEPTION_L(
5282                     CIM_ERR_INVALID_PARAMETER,
5283                     MessageLoaderParms(
5284                         _MSG_INVALID_VALUE_FOR_PROPERTY_KEY,
5285                         _MSG_INVALID_VALUE_FOR_PROPERTY,
5286                         theValue,
5287                         propertyName.getString()));
5288
5289             }
5290
5291             // Check for valid values that are not supported
5292             // Note: Supported values are a subset of the valid values
5293             // Some valid values, as defined in the MOF, are not currently
5294             // supported
5295             if (!Contains(supportedValues, theValue))
5296             {
5297                 PEG_METHOD_EXIT();
5298                 throw PEGASUS_CIM_EXCEPTION_L(
5299                     CIM_ERR_NOT_SUPPORTED,
5300                     MessageLoaderParms(
5301                         _MSG_UNSUPPORTED_VALUE_FOR_PROPERTY_KEY,
5302                         _MSG_UNSUPPORTED_VALUE_FOR_PROPERTY,
5303                         theValue,
5304                         propertyName.getString()));
5305             }
5306         }
5307     }
5308
5309     PEG_METHOD_EXIT ();
5310 }
5311
5312 Boolean IndicationService::_canModify (
5313     const CIMModifyInstanceRequestMessage * request,
5314     const CIMObjectPath& instanceReference,
5315     const CIMInstance& instance,
5316     CIMInstance& modifiedInstance)
5317 {
5318     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "IndicationService::_canModify");
5319
5320     //
5321     //  Currently, only modification allowed is of Subscription State
5322     //  property in Subscription class
5323     //
5324     if (!(instanceReference.getClassName ().equal
5325         (PEGASUS_CLASSNAME_INDSUBSCRIPTION)) &&
5326     !(instanceReference.getClassName ().equal
5327     (PEGASUS_CLASSNAME_FORMATTEDINDSUBSCRIPTION)))
5328     {
5329         PEG_METHOD_EXIT ();
5330         throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, String::EMPTY);
5331     }
5332
5333     if (request->includeQualifiers)
5334     {
5335         PEG_METHOD_EXIT ();
5336         throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, String::EMPTY);
5337     }
5338
5339     //
5340     //  Request is invalid if property list is null, meaning all properties
5341     //  are to be updated
5342     //
5343     if (request->propertyList.isNull ())
5344     {
5345         PEG_METHOD_EXIT ();
5346         throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, String::EMPTY);
5347     }
5348
5349     //
5350     //  Request is invalid if more than one property is specified
5351     //
5352     else if (request->propertyList.size() > 1)
5353     {
5354         PEG_METHOD_EXIT();
5355         throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, String::EMPTY);
5356     }
5357
5358     //
5359     //  For request to be valid, zero or one property must be specified
5360     //  If one property specified, it must be Subscription State property
5361     //
5362     else if ((request->propertyList.size() == 1) &&
5363              (!request->propertyList[0].equal(
5364                    PEGASUS_PROPERTYNAME_SUBSCRIPTION_STATE)))
5365     {
5366         PEG_METHOD_EXIT();
5367         throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, String::EMPTY);
5368     }
5369
5370     //
5371     //  Check the SubscriptionState property in the modified instance
5372     //
5373     _checkPropertyWithOther(
5374         modifiedInstance,
5375         PEGASUS_PROPERTYNAME_SUBSCRIPTION_STATE,
5376         _PROPERTY_OTHERSTATE,
5377         (Uint16) STATE_ENABLED,
5378         (Uint16) STATE_OTHER,
5379         _validStates,
5380         _supportedStates);
5381
5382     //
5383     //  Get creator from instance
5384     //
5385     String creator;
5386     if (!_getCreator (instance, creator))
5387     {
5388         //
5389         //  This instance from the repository is corrupted
5390         //
5391         PEG_METHOD_EXIT ();
5392         MessageLoaderParms parms(_MSG_INVALID_INSTANCES_KEY,
5393             _MSG_INVALID_INSTANCES);
5394         throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, parms);
5395     }
5396
5397     //
5398     //  Current user must be privileged user or instance Creator to modify
5399     //  NOTE: if authentication was not turned on when instance was created,
5400     //  instance creator will be String::EMPTY
5401     //  If creator is String::EMPTY, anyone may modify or delete the
5402     //  instance
5403     //
5404     String currentUser = ((IdentityContainer)request->operationContext.get
5405         (IdentityContainer :: NAME)).getUserName();
5406     if ((creator != String::EMPTY) &&
5407 #ifndef PEGASUS_OS_ZOS
5408         (!System::isPrivilegedUser (currentUser)) &&
5409 #endif
5410         (currentUser != creator))
5411     {
5412         PEG_METHOD_EXIT ();
5413         throw PEGASUS_CIM_EXCEPTION(CIM_ERR_ACCESS_DENIED, String::EMPTY);
5414     }
5415
5416     PEG_METHOD_EXIT ();
5417     return true;
5418 }
5419
5420 Boolean IndicationService::_canDelete (
5421     const CIMObjectPath& instanceReference,
5422     const CIMNamespaceName& nameSpace,
5423     const String& currentUser)
5424 {
5425     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "IndicationService::_canDelete");
5426
5427     CIMName superClass;
5428     CIMName propName;
5429
5430     //
5431     //  Get the instance to be deleted from the repository
5432     //
5433     CIMInstance instance;
5434
5435     instance = _subscriptionRepository->getInstance
5436         (nameSpace, instanceReference);
5437
5438     //
5439     //  Get creator from instance
5440     //
5441     String creator;
5442     if (!_getCreator (instance, creator))
5443     {
5444         //
5445         //  This instance from the repository is corrupted
5446         //  Allow the delete if a Privileged User
5447         //      (or authentication turned off),
5448         //  Otherwise disallow as access denied
5449         //
5450 #ifndef PEGASUS_OS_ZOS
5451         if ((!System::isPrivilegedUser (currentUser)) &&
5452             (currentUser != String::EMPTY))
5453         {
5454             PEG_METHOD_EXIT ();
5455             throw PEGASUS_CIM_EXCEPTION (CIM_ERR_ACCESS_DENIED, String::EMPTY);
5456         }
5457 #endif
5458     }
5459
5460     //
5461     //  Current user must be privileged user or instance Creator to delete
5462     //  NOTE: if authentication was not turned on when instance was created,
5463     //  instance creator will be String::EMPTY
5464     //  If creator is String::EMPTY, anyone may modify or delete the
5465     //  instance
5466     //
5467     if ((creator != String::EMPTY) &&
5468 #ifndef PEGASUS_OS_ZOS
5469         (!System::isPrivilegedUser (currentUser)) &&
5470 #endif
5471         (currentUser != creator))
5472     {
5473         PEG_METHOD_EXIT ();
5474         throw PEGASUS_CIM_EXCEPTION(CIM_ERR_ACCESS_DENIED, String::EMPTY);
5475     }
5476
5477     //
5478     //  Get the class and superclass of the instance to be deleted
5479     //
5480     CIMClass refClass;
5481
5482     refClass = _subscriptionRepository->getClass (nameSpace,
5483         instanceReference.getClassName (), true, true, false,
5484         CIMPropertyList ());
5485     superClass = refClass.getSuperClassName();
5486
5487     //
5488     //  If the class is Filter or superclass is Handler or Listener Destination,
5489     //  check for subscription instances referring to the instance to be deleted
5490     //
5491     if ((superClass.equal (PEGASUS_CLASSNAME_INDHANDLER)) ||
5492         (superClass.equal (PEGASUS_CLASSNAME_LSTNRDST)) ||
5493         (instanceReference.getClassName().equal (PEGASUS_CLASSNAME_INDFILTER)))
5494     {
5495         if (instanceReference.getClassName ().equal
5496                (PEGASUS_CLASSNAME_INDFILTER))
5497         {
5498             propName = PEGASUS_PROPERTYNAME_FILTER;
5499         }
5500         else if ((superClass.equal (PEGASUS_CLASSNAME_INDHANDLER)) ||
5501             (superClass.equal (PEGASUS_CLASSNAME_LSTNRDST)))
5502         {
5503             propName = PEGASUS_PROPERTYNAME_HANDLER;
5504
5505             //
5506             //  If deleting transient handler, first delete any referencing
5507             //  subscriptions
5508             //
5509             if (_subscriptionRepository->isTransient (nameSpace,
5510                 instanceReference))
5511             {
5512                 _deleteReferencingSubscriptions (nameSpace, propName,
5513                     instanceReference);
5514                 PEG_METHOD_EXIT ();
5515                 return true;
5516             }
5517         }
5518
5519         //
5520         //  Get all the subscriptions from the repository
5521         //
5522         Array<CIMInstance> subscriptions =
5523             _subscriptionRepository->getAllSubscriptions ();
5524
5525         CIMValue propValue;
5526
5527         //
5528         //  Check each subscription for a reference to the instance to be
5529         //  deleted
5530         //
5531         for (Uint32 i = 0; i < subscriptions.size(); i++)
5532         {
5533             //
5534             //  Get the subscription Filter or Handler property value
5535             //
5536             propValue = subscriptions[i].getProperty
5537                 (subscriptions[i].findProperty
5538                 (propName)).getValue();
5539
5540             CIMObjectPath ref;
5541             propValue.get (ref);
5542
5543             //
5544             //  If the Filter or Handler reference property value includes
5545             //  namespace, check if it is the namespace of the Filter or Handler
5546             //  being deleted.
5547             //  If the Filter or Handler reference property value does not
5548             //  include namespace, check if the current subscription namespace
5549             //  is the namespace of the Filter or Handler being deleted.
5550             //
5551             CIMNamespaceName instanceNS = ref.getNameSpace ();
5552             if (((instanceNS.isNull ()) &&
5553                 (subscriptions[i].getPath ().getNameSpace () == nameSpace))
5554                 || (instanceNS == nameSpace))
5555             {
5556
5557                 //
5558                 //  Remove Host and Namespace from reference property value, if
5559                 //  present, before comparing
5560                 //
5561                 CIMObjectPath path ("", CIMNamespaceName (),
5562                     ref.getClassName (), ref.getKeyBindings ());
5563
5564                 //
5565                 //  Remove Host and Namespace from reference of instance to be
5566                 //  deleted, if present, before comparing
5567                 //
5568                 CIMObjectPath iref ("", CIMNamespaceName (),
5569                     instanceReference.getClassName (),
5570                     instanceReference.getKeyBindings ());
5571
5572                 //
5573                 //  If the current subscription Filter or Handler is the
5574                 //  instance to be deleted, it may not be deleted
5575                 //
5576                 if (iref == path)
5577                 {
5578                     PEG_METHOD_EXIT ();
5579                     throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED,
5580                         MessageLoaderParms(
5581                             "IndicationService.IndicationService."
5582                                 "_MSG_REFERENCED",
5583                             "A filter or handler referenced by a subscription "
5584                                 "cannot be deleted."));
5585                 }
5586             }
5587         }
5588     }
5589
5590     PEG_METHOD_EXIT ();
5591     return true;
5592 }
5593
5594 Array<CIMInstance> IndicationService::_getMatchingSubscriptions (
5595     const CIMName& supportedClass,
5596     const Array<CIMNamespaceName> nameSpaces,
5597     const CIMPropertyList& supportedProperties,
5598     const Boolean checkProvider,
5599     const CIMInstance& provider)
5600 {
5601     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
5602         "IndicationService::_getMatchingSubscriptions");
5603
5604     Array<CIMInstance> matchingSubscriptions;
5605     Array<CIMInstance> subscriptions;
5606
5607     subscriptions = _subscriptionTable->getMatchingSubscriptions
5608         (supportedClass, nameSpaces, checkProvider, provider);
5609
5610     for (Uint32 i = 0; i < subscriptions.size (); i++)
5611     {
5612         Boolean match = true;
5613
5614         //
5615         //  If supported properties is null (all properties)
5616         //  the subscription can be supported
5617         //
5618         if (!supportedProperties.isNull ())
5619         {
5620             String filterQuery;
5621             String queryLanguage;
5622             CIMName indicationClassName;
5623             CIMNamespaceName sourceNameSpace;
5624             CIMPropertyList propertyList;
5625             String filterName;
5626
5627             try
5628             {
5629                 //
5630                 //  Get filter properties
5631                 //
5632                 _subscriptionRepository->getFilterProperties
5633                     (subscriptions[i], filterQuery, sourceNameSpace,
5634                      queryLanguage, filterName);
5635
5636                 QueryExpression queryExpr = _getQueryExpression(
5637                     filterQuery, queryLanguage, sourceNameSpace);
5638
5639                 // Get the class paths in the FROM list
5640                 // Since neither WQL nor CQL support joins, so we can
5641                 // assume one class path.
5642                 indicationClassName =
5643                     queryExpr.getClassPathList()[0].getClassName();
5644
5645                 if (!_subscriptionRepository->validateIndicationClassName(
5646                     indicationClassName, sourceNameSpace))
5647                 {
5648                     // Invalid FROM class, skip the subscription
5649                     continue;
5650                 }
5651
5652                 //
5653                 //  Get required property list from filter query (WHERE clause)
5654                 //
5655                 //  Note that the supportedClass is passed in,
5656                 //  not the indicationClassName.
5657                 //  The supportedClass is the class of the indication
5658                 //  instance, while the indicationClassName is the FROM class.
5659                 //  This is needed because CQL can have class scoping operators
5660                 //  on properties that may not be the same class
5661                 //  as the FROM class.  The required properties
5662                 //  for an indication are based on its class,
5663                 //  not the FROM class.
5664                 //
5665                 //  Also note that for CQL, this does not return
5666                 //  required embedded object properties.
5667                 propertyList = _getPropertyList (queryExpr,
5668                                              sourceNameSpace,
5669                                              supportedClass);
5670
5671                 //
5672                 //  If the subscription requires all properties,
5673                 //  but supported property list does not include all
5674                 //  properties, the subscription cannot be supported
5675                 //
5676                 if (propertyList.isNull ())
5677                 {
5678                     //
5679                     //  Current subscription does not match
5680                     //  Continue to next subscription in list
5681                     //
5682                     continue;
5683                 }
5684                 else
5685                 {
5686                     //
5687                     //  Compare subscription required property list
5688                     //  with supported property list
5689                     //
5690                     for (Uint32 j = 0;
5691                          j < propertyList.size () && match;
5692                          j++)
5693                     {
5694                         if (!ContainsCIMName
5695                             (supportedProperties.getPropertyNameArray(),
5696                             propertyList[j]))
5697                         {
5698                             match = false;
5699                             break;
5700                         }
5701                     }
5702                 }
5703             }
5704             catch(const Exception & e)
5705             {
5706                 // This subscription is invalid
5707                 // skip it
5708                PEG_TRACE ((TRC_DISCARDED_DATA, Tracer::LEVEL2,
5709                     "Exception caught trying to verify required properties"
5710                     " in a subscription are all contained in the list of"
5711                     " supported indication properties: %s",
5712                     (const char *) e.getMessage ().getCString()));
5713                 continue;
5714             }
5715             catch(const exception & e)
5716             {
5717                 // This subscription is invalid
5718                 // skip it
5719                PEG_TRACE ((TRC_DISCARDED_DATA, Tracer::LEVEL2,
5720                     "Exception caught trying to verify required properties"
5721                     " in a subscription are all contained in the list of"
5722                     " supported indication properties: %s", e.what ()));
5723                 continue;
5724             }
5725             catch(...)
5726             {
5727                 // This subscription is invalid
5728                 // skip it
5729                 PEG_TRACE_CSTRING (TRC_DISCARDED_DATA, Tracer::LEVEL2,
5730                     "Unknown exception caught trying to verify "
5731                     "required properties in a subscription are all contained "
5732                     "in the list of supported indication properties.");
5733                 continue;
5734             }
5735         }
5736
5737         if (match)
5738         {
5739             //
5740             //  Add current subscription to list
5741             //
5742             matchingSubscriptions.append (subscriptions[i]);
5743         }
5744     }
5745
5746     PEG_METHOD_EXIT ();
5747     return matchingSubscriptions;
5748 }
5749
5750 void IndicationService::_getModifiedSubscriptions (
5751     const CIMName& supportedClass,
5752     const Array<CIMNamespaceName>& newNameSpaces,
5753     const Array<CIMNamespaceName>& oldNameSpaces,
5754     const CIMPropertyList& newProperties,
5755     const CIMPropertyList& oldProperties,
5756     Array<CIMInstance>& newSubscriptions,
5757     Array<CIMInstance>& formerSubscriptions)
5758 {
5759     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
5760         "IndicationService::_getModifiedSubscriptions");
5761
5762     Array<CIMInstance> newList;
5763     Array<CIMInstance> formerList;
5764     Array<CIMInstance> bothList;
5765
5766     newSubscriptions.clear ();
5767     formerSubscriptions.clear ();
5768
5769     //
5770     //  For each newly supported namespace, lookup to retrieve list of
5771     //  subscriptions for the indication class-source namespace pair
5772     //
5773     newList = _subscriptionTable->getMatchingSubscriptions
5774         (supportedClass, newNameSpaces);
5775
5776     //
5777     //  For each formerly supported namespace, lookup to retrieve list of
5778     //  subscriptions for the indication class-source namespace pair
5779     //
5780     formerList = _subscriptionTable->getMatchingSubscriptions
5781         (supportedClass, oldNameSpaces);
5782
5783     //
5784     //  Find subscriptions that appear in both lists, and move them to a third
5785     //  list
5786     //
5787     Sint8 found;
5788     for (Uint32 p = 0; p < newList.size (); p++)
5789     {
5790         found = -1;
5791         for (Uint32 q = 0; q < formerList.size (); q++)
5792         {
5793             if (newList[p].identical (formerList[q]))
5794             {
5795                 found = q;
5796                 bothList.append (newList[p]);
5797                 break;
5798             }
5799         }
5800         if (found >= 0)
5801         {
5802             newList.remove (p);
5803             p--;
5804             formerList.remove (found);
5805         }
5806     }
5807
5808     //
5809     //  For indicationClassName-sourceNamespace pair that is now supported, but
5810     //  previously was not, add to list of newly supported subscriptions if
5811     //  required properties are now supported
5812     //
5813     for (Uint32 n = 0; n < newList.size (); n++)
5814     {
5815         String filterQuery;
5816         String queryLanguage;
5817         CIMName indicationClassName;
5818         CIMNamespaceName sourceNameSpace;
5819         CIMPropertyList requiredProperties;
5820         String filterName;
5821
5822         //
5823         //  Get filter properties
5824         //
5825         _subscriptionRepository->getFilterProperties (newList[n], filterQuery,
5826             sourceNameSpace, queryLanguage, filterName);
5827         QueryExpression queryExpression = _getQueryExpression(
5828             filterQuery, queryLanguage, sourceNameSpace);
5829
5830         //
5831         //  Get indication class name from filter query (FROM clause)
5832         //
5833         indicationClassName = _getIndicationClassName (queryExpression,
5834             sourceNameSpace);
5835
5836         //
5837         //  Get required property list from filter query (WHERE clause)
5838         //
5839         //  Note: the supportedClass is passed to _getPropertyList
5840         //  rather than the FROM class because CQL could have
5841         //  class scoping operators that scope properties to
5842         //  specific subclasses of the FROM.
5843         //
5844         requiredProperties = _getPropertyList (queryExpression,
5845             sourceNameSpace, supportedClass);
5846
5847         //
5848         //  Check if required properties are now supported
5849         //
5850         if (_inPropertyList (requiredProperties, newProperties))
5851         {
5852             newSubscriptions.append (newList[n]);
5853         }
5854     }
5855
5856     //
5857     //  For indicationClassName-sourceNamespace pair that was previously
5858     //  supported, but now is not, add to list of formerly supported
5859     //  subscriptions
5860     //
5861     for (Uint32 f = 0; f < formerList.size (); f++)
5862     {
5863         formerSubscriptions.append (formerList[f]);
5864     }
5865
5866     //
5867     //  For indicationClassName-sourceNamespace pair that is now supported,
5868     //  and was also previously supported, add to appropriate list, based on
5869     //  required properties
5870     //
5871     for (Uint32 b = 0; b < bothList.size (); b++)
5872     {
5873         String filterQuery;
5874         String queryLanguage;
5875         CIMName indicationClassName;
5876         CIMNamespaceName sourceNameSpace;
5877         CIMPropertyList requiredProperties;
5878         Boolean newMatch = false;
5879         Boolean formerMatch = false;
5880         String filterName;
5881
5882         //
5883         //  Get filter properties
5884         //
5885         _subscriptionRepository->getFilterProperties (bothList[b], filterQuery,
5886             sourceNameSpace, queryLanguage, filterName);
5887         QueryExpression queryExpression = _getQueryExpression(
5888             filterQuery, queryLanguage, sourceNameSpace);
5889
5890         //
5891         //  Get indication class name from filter query (FROM clause)
5892         //
5893         indicationClassName = _getIndicationClassName (queryExpression,
5894             sourceNameSpace);
5895
5896         //
5897         //  Get required property list from filter query (WHERE clause)
5898         //
5899         //  Note: the supportedClass is passed to _getPropertyList
5900         //  rather than the FROM class because CQL could have
5901         //  class scoping operators that scope properties to
5902         //  specific subclasses of the FROM.
5903         //
5904         requiredProperties = _getPropertyList (queryExpression,
5905             sourceNameSpace, supportedClass);
5906
5907         //
5908         //  Check required properties
5909         //
5910         newMatch = _inPropertyList (requiredProperties,
5911             newProperties);
5912         formerMatch = _inPropertyList (requiredProperties,
5913             oldProperties);
5914
5915         //
5916         //  Add current subscription to appropriate list
5917         //
5918         if (newMatch && !formerMatch)
5919         {
5920             newSubscriptions.append (bothList[b]);
5921         }
5922         else if (!newMatch && formerMatch)
5923         {
5924             formerSubscriptions.append (bothList[b]);
5925         }
5926     }
5927
5928     PEG_METHOD_EXIT ();
5929 }
5930
5931 Boolean IndicationService::_inPropertyList (
5932     const CIMPropertyList& requiredProperties,
5933     const CIMPropertyList& supportedProperties)
5934 {
5935     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
5936         "IndicationService::_inPropertyList");
5937
5938     //
5939     //  If property list is null (all properties)
5940     //  all the required properties are supported
5941     //
5942     if (supportedProperties.isNull ())
5943     {
5944         PEG_METHOD_EXIT();
5945         return true;
5946     }
5947     else
5948     {
5949         //
5950         //  If the subscription requires all properties,
5951         //  but property list does not include all
5952         //  properties, the required properties cannot be supported
5953         //
5954         if (requiredProperties.isNull ())
5955         {
5956             PEG_METHOD_EXIT();
5957             return false;
5958         }
5959         else
5960         {
5961             //
5962             //  Compare required property list
5963             //  with property list
5964             //
5965             for (Uint32 i = 0; i < requiredProperties.size (); i++)
5966             {
5967                 if (!ContainsCIMName
5968                     (supportedProperties.getPropertyNameArray (),
5969                     requiredProperties[i]))
5970                 {
5971                     PEG_METHOD_EXIT();
5972                     return false;
5973                 }
5974             }
5975         }
5976     }
5977
5978     PEG_METHOD_EXIT ();
5979     return true;
5980 }
5981
5982 QueryExpression IndicationService::_getQueryExpression(
5983     const String& filterQuery,
5984     const String& queryLanguage,
5985     const CIMNamespaceName& ns) const
5986 {
5987     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
5988         "IndicationService::_getQueryExpression");
5989
5990     try
5991     {
5992         RepositoryQueryContext ctx(ns, _cimRepository);
5993         QueryExpression queryExpression(queryLanguage, filterQuery, ctx);
5994         PEG_METHOD_EXIT();
5995         return queryExpression;
5996     }
5997     catch (QueryParseException& qpe)
5998     {
5999         String exceptionStr = qpe.getMessage();
6000
6001         PEG_METHOD_EXIT();
6002         throw PEGASUS_CIM_EXCEPTION(CIM_ERR_INVALID_PARAMETER, exceptionStr);
6003     }
6004     catch (ParseError& pe)
6005     {
6006         String exceptionStr = pe.getMessage();
6007
6008         PEG_METHOD_EXIT();
6009         throw PEGASUS_CIM_EXCEPTION(CIM_ERR_INVALID_PARAMETER, exceptionStr);
6010     }
6011     catch (MissingNullTerminator& mnt)
6012     {
6013         String exceptionStr = mnt.getMessage();
6014
6015         PEG_METHOD_EXIT();
6016         throw PEGASUS_CIM_EXCEPTION(CIM_ERR_INVALID_PARAMETER, exceptionStr);
6017     }
6018 }
6019
6020 CIMName IndicationService::_getIndicationClassName (
6021     const QueryExpression& queryExpression,
6022     const CIMNamespaceName& nameSpaceName) const
6023 {
6024     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
6025         "IndicationService::_getIndicationClassName");
6026
6027     CIMName indicationClassName;
6028     Array<CIMName> indicationSubclasses;
6029
6030     // Get the class paths in the FROM list.
6031     // Note: neither WQL nor CQL support joins, so we can
6032     // assume one class path.
6033     // Note: neither WQL not CQL support wbem-uri for class paths,
6034     // so we can ignore the parts of the path before the class name.
6035     Array<CIMObjectPath> fromPaths = queryExpression.getClassPathList();
6036     indicationClassName = fromPaths[0].getClassName();
6037
6038     //
6039     //  Validate that class is an Indication class
6040     //  The Indication Qualifier should exist and have the value True
6041     //
6042     Boolean validClass = _subscriptionRepository->validateIndicationClassName
6043         (indicationClassName, nameSpaceName);
6044
6045     if (!validClass)
6046     {
6047         PEG_METHOD_EXIT();
6048         throw PEGASUS_CIM_EXCEPTION_L(
6049             CIM_ERR_INVALID_PARAMETER,
6050             MessageLoaderParms(
6051                 "IndicationService.IndicationService."
6052                     "_MSG_INVALID_CLASSNAME_IN_FROM_PROPERTY",
6053                 "The Indication class name $0 is not valid in the FROM clause "
6054                     "of $1 $2 property.",
6055                 indicationClassName.getString(),
6056                 PEGASUS_CLASSNAME_INDFILTER.getString(),
6057                 PEGASUS_PROPERTYNAME_QUERY.getString()));
6058     }
6059
6060     PEG_METHOD_EXIT ();
6061     return indicationClassName;
6062 }
6063
6064 Array<ProviderClassList> IndicationService::_getIndicationProviders (
6065     const QueryExpression& queryExpression,
6066     const CIMNamespaceName& nameSpace,
6067     const CIMName& indicationClassName,
6068     const Array<CIMName>& indicationSubclasses) const
6069 {
6070     PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
6071         "IndicationService::_getIndicationProviders");
6072
6073     ProviderClassList provider;
6074     Array<ProviderClassList> indicationProviders;
6075     Array<CIMInstance> providerInstances;
6076     Array<CIMInstance> providerModuleInstances;
6077
6078     CIMPropertyList requiredPropertyList;
6079
6080     //
6081     //  For each indication subclass, get providers
6082     //
6083     for (Uint32 i = 0, n = indicationSubclasses.size (); i < n; i++)
6084     {
6085         //  Get required property list from filter query (WHERE clause)
6086         //  from this indication subclass
6087         //
6088         requiredPropertyList = _getPropertyList (queryExpression,
6089                                                  nameSpace,
6090                                                  indicationSubclasses[i]);
6091
6092         //
6093         //  Get providers that can serve the subscription
6094         //
6095         providerInstances.clear ();
6096         providerModuleInstances.clear ();
6097         if (_providerRegManager->getIndicationProviders
6098                 (nameSpace,
6099                  indicationSubclasses[i],
6100                  requiredPropertyList,
6101                  providerInstances,
6102                  providerModuleInstances))
6103         {
6104             PEGASUS_ASSERT (providerInstances.size () ==
6105                             providerModuleInstances.size ());
6106
6107             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
6108                 "%u indication provider(s) found for class %s",
6109                 providerInstances.size (),
6110                 (const char *)
6111                 indicationSubclasses[i].getString ().getCString ()));
6112
6113             //
6114             //  Merge into list of ProviderClassList structs
6115             //
6116             for (Uint32 j = 0, numI = providerInstances.size (); j < numI; j++)
6117             {
6118                 provider.classList.clear ();
6119                 Boolean duplicate = false;
6120
6121                 //
6122                 //  See if indication provider is already in list
6123                 //
6124                 for (Uint32 k = 0, numP = indicationProviders.size ();
6125                      k < numP && !duplicate; k++)
6126                 {
6127                     if ((providerInstances[j].getPath ().identical
6128                         (indicationProviders[k].provider.getPath ())) &&
6129                         (providerModuleInstances[j].getPath ().identical
6130                         (indicationProviders[k].providerModule.getPath ())))
6131                     {
6132                         //
6133                         //  Indication provider is already in list
6134                         //  Add subclass to provider's class list
6135                         //
6136                         indicationProviders[k].classList.append
6137                             (indicationSubclasses[i]);
6138                         duplicate = true;
6139                     }
6140                 }
6141
6142                 if (!duplicate)
6143                 {
6144                     //
6145                     //  Current provider is not yet in list
6146                     //  Create new list entry
6147                     //
6148                     provider.provider = providerInstances[j];
6149                     provider.providerModule = providerModuleInstances[j];
6150                     provider.classList.append (indicationSubclasses[i]);
6151 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
6152                     String remoteInformation;
6153                     Boolean isRemote = _cimRepository->isRemoteNameSpace(
6154                         nameSpace, remoteInformation);
6155                     provider.isRemoteNameSpace = isRemote;
6156                     provider.remoteInfo = remoteInformation;
6157 #endif
6158                     indicationProviders.append(provider);
6159                 }
6160             }  // for each indication provider instance
6161         }  // if any providers
6162     }  // for each indication subclass
6163
6164     PEG_METHOD_EXIT();
6165     return indicationProviders;
6166 }
6167
6168 CIMPropertyList IndicationService::_getPropertyList(
6169     const QueryExpression& queryExpression,
6170     const CIMNamespaceName& nameSpaceName,
6171     const CIMName& indicationClassName) const
6172 {
6173     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6174         "IndicationService::_getPropertyList");
6175
6176     CIMPropertyList propertyList;
6177
6178     //  Get all the properties referenced in the condition (WHERE clause)
6179     //  Note: for CQL, this only returns the properties directly on the
6180     //  class name passed in, not any properties on embedded objects.
6181     //
6182     try
6183     {
6184       CIMObjectPath classPath(String::EMPTY,
6185                                nameSpaceName,
6186                                indicationClassName);
6187       propertyList = queryExpression.getWherePropertyList(classPath);
6188     }
6189     catch (QueryException& qe)
6190     {
6191       // The class path was not the FROM class, or a subclass
6192       // of the FROM class.
6193       String exceptionStr = qe.getMessage();
6194
6195       PEG_METHOD_EXIT();
6196       throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED, exceptionStr);
6197     }
6198
6199     if (propertyList.isNull())
6200     {
6201         //
6202         //  Return null property list for all properties
6203         //
6204         PEG_METHOD_EXIT();
6205         return propertyList;
6206     }
6207     else
6208     {
6209         Array<CIMName> propertyArray;
6210
6211         //  Get the property names
6212         //
6213         propertyArray = propertyList.getPropertyNameArray();
6214
6215         Array<CIMName> indicationClassProperties;
6216         PEG_METHOD_EXIT();
6217         return _checkPropertyList(propertyArray, nameSpaceName,
6218             indicationClassName, indicationClassProperties);
6219     }
6220 }
6221
6222 CIMPropertyList IndicationService::_checkPropertyList(
6223     const Array<CIMName>& propertyList,
6224     const CIMNamespaceName& nameSpaceName,
6225     const CIMName& indicationClassName,
6226     Array<CIMName>& indicationClassProperties) const
6227 {
6228     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6229         "IndicationService::_checkPropertyList");
6230
6231     //
6232     //  Check if list includes all properties in class
6233     //  If so, must be set to NULL
6234     //
6235     CIMClass indicationClass;
6236
6237     //
6238     //  Get the indication class object from the repository
6239     //  Specify localOnly=false because superclass properties are needed
6240     //  Specify includeQualifiers=false because qualifiers are not needed
6241     //
6242     indicationClass = _subscriptionRepository->getClass(
6243         nameSpaceName, indicationClassName, false, false, false,
6244         CIMPropertyList());
6245
6246     Boolean allProperties = true;
6247     for (Uint32 i = 0; i < indicationClass.getPropertyCount(); i++)
6248     {
6249         indicationClassProperties.append(
6250             indicationClass.getProperty(i).getName());
6251         if (!ContainsCIMName(propertyList,
6252             indicationClass.getProperty(i).getName()))
6253         {
6254             allProperties = false;
6255         }
6256     }
6257
6258     if (allProperties)
6259     {
6260         //
6261         //  Return NULL CIMPropertyList
6262         //
6263         PEG_METHOD_EXIT();
6264         return CIMPropertyList();
6265     }
6266     else
6267     {
6268         PEG_METHOD_EXIT();
6269         return CIMPropertyList(propertyList);
6270     }
6271 }
6272
6273 String IndicationService::_getCondition(
6274     const String& filterQuery) const
6275 {
6276     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6277         "IndicationService::_getCondition");
6278
6279     String condition;
6280
6281     //
6282     //  Get condition substring from filter query
6283     //
6284     if (filterQuery.find(_QUERY_WHERE) != PEG_NOT_FOUND)
6285     {
6286         condition = filterQuery.subString(filterQuery.find(_QUERY_WHERE) + 6);
6287     }
6288
6289     PEG_METHOD_EXIT();
6290     return condition;
6291 }
6292
6293 void IndicationService::_deleteReferencingSubscriptions(
6294     const CIMNamespaceName& nameSpace,
6295     const CIMName& referenceProperty,
6296     const CIMObjectPath& handler)
6297 {
6298     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6299         "IndicationService::_deleteReferencingSubscriptions");
6300
6301     Array<CIMInstance> deletedSubscriptions;
6302
6303     //
6304     //  Delete referencing subscriptions from the repository
6305     //
6306     deletedSubscriptions =
6307         _subscriptionRepository->deleteReferencingSubscriptions(
6308             nameSpace, referenceProperty, handler);
6309
6310     //
6311     //  Send delete request to each provider for each deleted subscription
6312     //
6313     for (Uint32 i = 0; i < deletedSubscriptions.size(); i++)
6314     {
6315         Array<ProviderClassList> indicationProviders;
6316         Array<CIMName> indicationSubclasses;
6317         CIMNamespaceName sourceNamespaceName;
6318
6319         indicationProviders = _getDeleteParams(deletedSubscriptions[i],
6320             indicationSubclasses, sourceNamespaceName);
6321
6322         //
6323         //  Send Delete requests
6324         //
6325         //  NOTE: These Delete requests are not associated with a user
6326         //  request, so there is no associated authType or userName
6327         //  The Creator from the subscription instance is used for userName,
6328         //  and authType is not set
6329         //
6330         CIMInstance instance = deletedSubscriptions[i];
6331         String creator;
6332         _getCreator(instance, creator);
6333
6334 // l10n start
6335         AcceptLanguageList acceptLangs;
6336         Uint32 propIndex = instance.findProperty(
6337             PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS);
6338         if (propIndex != PEG_NOT_FOUND)
6339         {
6340             String acceptLangsString;
6341             instance.getProperty(propIndex).getValue().get(
6342                 acceptLangsString);
6343             if (acceptLangsString.size())
6344             {
6345                 acceptLangs = LanguageParser::parseAcceptLanguageHeader(
6346                     acceptLangsString);
6347             }
6348         }
6349         ContentLanguageList contentLangs;
6350         propIndex = instance.findProperty(
6351             PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS);
6352         if (propIndex != PEG_NOT_FOUND)
6353         {
6354             String contentLangsString;
6355             instance.getProperty(propIndex).getValue().get(
6356                 contentLangsString);
6357             if (contentLangsString.size())
6358             {
6359                 contentLangs = LanguageParser::parseContentLanguageHeader(
6360                     contentLangsString);
6361             }
6362         }
6363 // l10n end
6364
6365         _sendAsyncDeleteRequests(
6366             indicationProviders,
6367             sourceNamespaceName,
6368             deletedSubscriptions[i],
6369             acceptLangs,
6370             contentLangs,
6371             0,  // no request
6372             indicationSubclasses,
6373             creator);
6374     }
6375
6376     PEG_METHOD_EXIT();
6377 }
6378
6379 Boolean IndicationService::_isExpired(
6380     const CIMInstance& instance) const
6381 {
6382     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "IndicationService::_isExpired");
6383
6384     Boolean isExpired = true;
6385     Uint64 timeRemaining = 0;
6386
6387     //
6388     //  Get time remaining, if subscription has a duration
6389     //
6390     if (_getTimeRemaining(instance, timeRemaining))
6391     {
6392         if (timeRemaining > 0)
6393         {
6394             isExpired = false;
6395         }
6396     }
6397     else
6398     {
6399         //
6400         //  If there is no duration, the subscription has no expiration date
6401         //
6402         isExpired = false;
6403     }
6404
6405     PEG_METHOD_EXIT();
6406     return isExpired;
6407 }
6408
6409 void IndicationService::_deleteExpiredSubscription(
6410     CIMObjectPath& subscription)
6411 {
6412     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6413         "IndicationService::_deleteExpiredSubscription");
6414
6415     CIMInstance subscriptionInstance;
6416
6417     //
6418     //  Delete instance from repository
6419     //
6420     subscriptionInstance =
6421         _subscriptionRepository->deleteSubscription(subscription);
6422
6423     //
6424     //  If a valid instance object was returned, the subscription was
6425     //  successfully deleted
6426     //
6427     if (!subscriptionInstance.isUninitialized())
6428     {
6429         //
6430         //  If subscription was active, send delete requests to providers
6431         //  and update hash tables
6432         //
6433         Uint16 subscriptionState;
6434         CIMValue subscriptionStateValue;
6435         subscriptionStateValue = subscriptionInstance.getProperty(
6436             subscriptionInstance.findProperty(
6437                 PEGASUS_PROPERTYNAME_SUBSCRIPTION_STATE)).getValue();
6438         subscriptionStateValue.get(subscriptionState);
6439
6440         if ((subscriptionState == STATE_ENABLED) ||
6441             (subscriptionState == STATE_ENABLEDDEGRADED))
6442         {
6443             Array<ProviderClassList> indicationProviders;
6444             Array<CIMName> indicationSubclasses;
6445             CIMNamespaceName sourceNamespaceName;
6446
6447             subscriptionInstance.setPath(subscription);
6448
6449             indicationProviders = _getDeleteParams(subscriptionInstance,
6450                 indicationSubclasses, sourceNamespaceName);
6451
6452             //
6453             //  Send Delete requests
6454             //
6455             //  NOTE: These Delete requests are not associated with a user
6456             //  request, so there is no associated authType or userName
6457             //  The Creator from the subscription instance is used for userName,
6458             //  and authType is not set
6459             //
6460             String creator;
6461             _getCreator(subscriptionInstance, creator);
6462
6463             //
6464             // Get the language tags that were saved with the subscription
6465             // instance
6466             //
6467             AcceptLanguageList acceptLangs;
6468             Uint32 propIndex = subscriptionInstance.findProperty(
6469                 PEGASUS_PROPERTYNAME_INDSUB_ACCEPTLANGS);
6470             if (propIndex != PEG_NOT_FOUND)
6471             {
6472                 String acceptLangsString;
6473                 subscriptionInstance.getProperty(propIndex).getValue().get(
6474                     acceptLangsString);
6475                 if (acceptLangsString.size())
6476                 {
6477                     acceptLangs = LanguageParser::parseAcceptLanguageHeader(
6478                         acceptLangsString);
6479                 }
6480             }
6481             ContentLanguageList contentLangs;
6482             propIndex = subscriptionInstance.findProperty(
6483                 PEGASUS_PROPERTYNAME_INDSUB_CONTENTLANGS);
6484             if (propIndex != PEG_NOT_FOUND)
6485             {
6486                 String contentLangsString;
6487                 subscriptionInstance.getProperty(propIndex).getValue().get(
6488                     contentLangsString);
6489                 if (contentLangsString.size())
6490                 {
6491                     contentLangs = LanguageParser::parseContentLanguageHeader(
6492                         contentLangsString);
6493                 }
6494             }
6495
6496             subscriptionInstance.setPath(subscription);
6497             _sendAsyncDeleteRequests(indicationProviders,
6498                 sourceNamespaceName, subscriptionInstance,
6499                 acceptLangs,
6500                 contentLangs,
6501                 0, // no request
6502                 indicationSubclasses,
6503                 creator);
6504         }
6505     }
6506     else
6507     {
6508         //
6509         //  The subscription may have already been deleted by another thread
6510         //
6511     }
6512
6513     PEG_METHOD_EXIT();
6514 }
6515
6516 Boolean IndicationService::_getTimeRemaining(
6517     const CIMInstance& instance,
6518     Uint64& timeRemaining) const
6519 {
6520     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6521         "IndicationService::_getTimeRemaining");
6522
6523     Boolean hasDuration = true;
6524     timeRemaining = 0;
6525
6526     //
6527     //  Calculate time remaining from subscription
6528     //  start time, subscription duration, and current date time
6529     //
6530
6531     //
6532     //  NOTE: It is assumed that the instance passed to this method is a
6533     //  subscription instance, and that the Start Time property exists
6534     //  and has a value
6535     //
6536
6537     //
6538     //  Get Subscription Start Time
6539     //
6540     CIMValue startTimeValue;
6541     CIMDateTime startTime;
6542     Uint32 startTimeIndex = instance.findProperty(_PROPERTY_STARTTIME);
6543     PEGASUS_ASSERT(startTimeIndex != PEG_NOT_FOUND);
6544     startTimeValue = instance.getProperty(startTimeIndex).getValue();
6545     PEGASUS_ASSERT(!(startTimeValue.isNull()));
6546     startTimeValue.get(startTime);
6547
6548     //
6549     //  Get Subscription Duration
6550     //
6551     Uint32 durationIndex = instance.findProperty(_PROPERTY_DURATION);
6552     if (durationIndex != PEG_NOT_FOUND)
6553     {
6554         CIMValue durationValue;
6555         durationValue = instance.getProperty(durationIndex).getValue();
6556         if (durationValue.isNull())
6557         {
6558             hasDuration = false;
6559         }
6560         else
6561         {
6562             Uint64 duration;
6563             durationValue.get(duration);
6564
6565             //
6566             //  A Start Time set to the _ZERO_INTERVAL_STRING indicates that
6567             //  the subscription has not yet been enabled for the first time
6568             //  In this case, the time remaining is equal to the Duration
6569             //
6570             if (startTime.isInterval())
6571             {
6572                 if (startTime.equal(CIMDateTime(_ZERO_INTERVAL_STRING)))
6573                 {
6574                     timeRemaining = (Sint64) duration;
6575                 }
6576
6577                 //
6578                 //  Any interval value other than _ZERO_INTERVAL_STRING
6579                 //  indicates an invalid Start Time value in the instance
6580                 //
6581                 else
6582                 {
6583                     PEGASUS_ASSERT(false);
6584                 }
6585             }
6586
6587             else
6588             {
6589                 //
6590                 //  Get current date time, and calculate Subscription Time
6591                 //  Remaining
6592                 //
6593                 CIMDateTime currentDateTime = CIMDateTime::getCurrentDateTime();
6594
6595                 Sint64 difference = CIMDateTime::getDifference(
6596                     startTime, currentDateTime);
6597                 PEGASUS_ASSERT(difference >= 0);
6598                 if (((Sint64) duration - difference) >= 0)
6599                 {
6600                     timeRemaining = (Sint64) duration - difference;
6601                 }
6602             }
6603         }
6604     }
6605     else
6606     {
6607         hasDuration = false;
6608     }
6609
6610     PEG_METHOD_EXIT();
6611     return hasDuration;
6612 }
6613
6614 void IndicationService::_setTimeRemaining(
6615     CIMInstance& instance)
6616 {
6617     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6618         "IndicationService::_setTimeRemaining");
6619
6620     Uint64 timeRemaining = 0;
6621     if (_getTimeRemaining(instance, timeRemaining))
6622     {
6623         //
6624         //  Add or set the value of the property with the calculated value
6625         //
6626         if (instance.findProperty(_PROPERTY_TIMEREMAINING) == PEG_NOT_FOUND)
6627         {
6628             instance.addProperty(
6629                 CIMProperty(_PROPERTY_TIMEREMAINING, timeRemaining));
6630         }
6631         else
6632         {
6633             CIMProperty remaining = instance.getProperty(
6634                 instance.findProperty(_PROPERTY_TIMEREMAINING));
6635             remaining.setValue(CIMValue(timeRemaining));
6636         }
6637     }
6638
6639     PEG_METHOD_EXIT();
6640 }
6641
6642 void IndicationService::_getCreateParams(
6643     const CIMInstance& subscriptionInstance,
6644     Array<CIMName>& indicationSubclasses,
6645     Array<ProviderClassList>& indicationProviders,
6646     CIMPropertyList& propertyList,
6647     CIMNamespaceName& sourceNameSpace,
6648     String& condition,
6649     String& query,
6650     String& queryLanguage)
6651 {
6652     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6653         "IndicationService::_getCreateParams");
6654
6655     CIMName indicationClassName;
6656     condition = String::EMPTY;
6657     query = String::EMPTY;
6658     queryLanguage = String::EMPTY;
6659     String filterName;
6660
6661     //
6662     //  Get filter properties
6663     //
6664     _subscriptionRepository->getFilterProperties(subscriptionInstance, query,
6665         sourceNameSpace, queryLanguage, filterName);
6666
6667     //
6668     //  Build the query expression from the filter query
6669     //
6670     QueryExpression queryExpression = _getQueryExpression(query,
6671                                                          queryLanguage,
6672                                                          sourceNameSpace);
6673
6674     //
6675     //  Get indication class name from filter query (FROM clause)
6676     //
6677     indicationClassName = _getIndicationClassName(queryExpression,
6678                                                    sourceNameSpace);
6679
6680     //
6681     //  Get list of subclass names for indication class
6682     //
6683     indicationSubclasses = _subscriptionRepository->getIndicationSubclasses(
6684         sourceNameSpace, indicationClassName);
6685
6686
6687     //
6688     //  Get indication provider class lists
6689     //
6690     indicationProviders = _getIndicationProviders(
6691          queryExpression,
6692          sourceNameSpace,
6693          indicationClassName,
6694          indicationSubclasses);
6695
6696     if (indicationProviders.size() > 0)
6697     {
6698         condition = _getCondition(query);
6699     }
6700
6701     PEG_METHOD_EXIT();
6702 }
6703
6704 void IndicationService::_getCreateParams(
6705     const CIMInstance& subscriptionInstance,
6706     Array<CIMName>& indicationSubclasses,
6707     CIMPropertyList& propertyList,
6708     CIMNamespaceName& sourceNameSpace,
6709     String& condition,
6710     String& query,
6711     String& queryLanguage)
6712 {
6713     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6714         "IndicationService::_getCreateParams");
6715
6716     condition = String::EMPTY;
6717     query = String::EMPTY;
6718     queryLanguage = String::EMPTY;
6719     String filterName;
6720
6721     //
6722     //  Get filter properties
6723     //
6724     _subscriptionRepository->getFilterProperties(subscriptionInstance, query,
6725         sourceNameSpace, queryLanguage, filterName);
6726     QueryExpression queryExpression = _getQueryExpression(
6727         query,
6728         queryLanguage,
6729         sourceNameSpace);
6730
6731     //
6732     //  Get indication class name from filter query (FROM clause)
6733     //
6734     CIMName indicationClassName =
6735         _getIndicationClassName(queryExpression, sourceNameSpace);
6736
6737     //
6738     //  Get required property list from filter query (WHERE clause)
6739     //
6740     propertyList = _getPropertyList(queryExpression,
6741         sourceNameSpace, indicationClassName);
6742
6743     //
6744     //  Get condition from filter query (WHERE clause)
6745     //
6746     condition = _getCondition(query);
6747
6748     //
6749     //  Get list of subclass names for indication class
6750     //
6751     indicationSubclasses = _subscriptionRepository->getIndicationSubclasses(
6752         sourceNameSpace, indicationClassName);
6753
6754     PEG_METHOD_EXIT();
6755 }
6756
6757 Array<ProviderClassList> IndicationService::_getDeleteParams(
6758     const CIMInstance& subscriptionInstance,
6759     Array<CIMName>& indicationSubclasses,
6760     CIMNamespaceName& sourceNameSpace)
6761 {
6762     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6763         "IndicationService::_getDeleteParams");
6764
6765     String filterQuery;
6766     String queryLanguage;
6767     String filterName;
6768     CIMName indicationClassName;
6769     Array<ProviderClassList> indicationProviders;
6770
6771     //
6772     //  Get filter properties
6773     //
6774     _subscriptionRepository->getFilterProperties(subscriptionInstance,
6775         filterQuery, sourceNameSpace, queryLanguage, filterName);
6776     QueryExpression queryExpression =
6777         _getQueryExpression(filterQuery, queryLanguage, sourceNameSpace);
6778
6779     //
6780     //  Get indication class name from filter query (FROM clause)
6781     //
6782     indicationClassName =
6783         _getIndicationClassName(queryExpression, sourceNameSpace);
6784
6785     //
6786     //  Get list of subclass names for indication class
6787     //
6788     indicationSubclasses = _subscriptionRepository->getIndicationSubclasses(
6789         sourceNameSpace, indicationClassName);
6790
6791     //
6792     //  Get indication provider class lists from Active Subscriptions table
6793     //
6794     ActiveSubscriptionsTableEntry tableValue;
6795     if (_subscriptionTable->getSubscriptionEntry(
6796             subscriptionInstance.getPath(), tableValue))
6797     {
6798         indicationProviders = tableValue.providers;
6799     }
6800     else
6801     {
6802         //
6803         //  Subscription not found in Active Subscriptions table
6804         //
6805     }
6806
6807     PEG_METHOD_EXIT();
6808     return indicationProviders;
6809 }
6810
6811 void IndicationService::_sendAsyncCreateRequests(
6812     const Array<ProviderClassList>& indicationProviders,
6813     const CIMNamespaceName& nameSpace,
6814     const CIMPropertyList& propertyList,
6815     const String& condition,
6816     const String& query,
6817     const String& queryLanguage,
6818     const CIMInstance& subscription,
6819     const AcceptLanguageList& acceptLangs,
6820     const ContentLanguageList& contentLangs,
6821     const CIMRequestMessage * origRequest,
6822     const Array<CIMName>& indicationSubclasses,
6823     const String& userName,
6824     const String& authType)
6825 {
6826     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6827         "IndicationService::_sendAsyncCreateRequests");
6828
6829     CIMValue propValue;
6830     Uint16 repeatNotificationPolicy;
6831
6832     // If there are no providers to accept the subscription, just return
6833     if (indicationProviders.size() == 0)
6834     {
6835         PEG_METHOD_EXIT();
6836         return;
6837     }
6838
6839 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
6840     _asyncRequestsPending++;
6841     AutoPtr<AtomicInt, DecAtomicInt> counter(&_asyncRequestsPending);
6842 #endif
6843
6844     //
6845     //  Get repeat notification policy value from subscription instance
6846     //
6847     propValue = subscription.getProperty(
6848         subscription.findProperty(
6849             _PROPERTY_REPEATNOTIFICATIONPOLICY)).getValue();
6850     propValue.get(repeatNotificationPolicy);
6851
6852     CIMRequestMessage * aggRequest=0;
6853
6854     if (origRequest == 0)
6855     {
6856         //
6857         //  Initialize -- no request associated with this create
6858         //
6859         aggRequest = 0;
6860     }
6861     else
6862     {
6863         //
6864         //  Create Instance or Modify Instance
6865         //
6866         switch (origRequest->getType())
6867         {
6868             case CIM_CREATE_INSTANCE_REQUEST_MESSAGE:
6869             {
6870                 CIMCreateInstanceRequestMessage * request =
6871                     (CIMCreateInstanceRequestMessage *) origRequest;
6872                 CIMCreateInstanceRequestMessage * requestCopy =
6873                     new CIMCreateInstanceRequestMessage(*request);
6874                 aggRequest = requestCopy;
6875                 break;
6876             }
6877
6878             case CIM_MODIFY_INSTANCE_REQUEST_MESSAGE:
6879             {
6880                 CIMModifyInstanceRequestMessage * request =
6881                     (CIMModifyInstanceRequestMessage *) origRequest;
6882                 CIMModifyInstanceRequestMessage * requestCopy =
6883                     new CIMModifyInstanceRequestMessage(*request);
6884                 aggRequest = requestCopy;
6885                 break;
6886             }
6887
6888             default:
6889             {
6890                 PEG_TRACE((TRC_INDICATION_SERVICE,Tracer::LEVEL1,
6891                     "Unexpected origRequest type %s "
6892                     "in _sendAsyncCreateRequests",
6893                     MessageTypeToString(origRequest->getType())));
6894                 PEGASUS_ASSERT(false);
6895                 break;
6896             }
6897         }
6898     }
6899
6900     //
6901     //  Create an aggregate object for the create subscription requests
6902     //
6903     IndicationOperationAggregate * operationAggregate =
6904         new IndicationOperationAggregate(aggRequest, indicationSubclasses);
6905     operationAggregate->setNumberIssued(indicationProviders.size());
6906
6907     //
6908     //  Send Create request to each provider
6909     //
6910     for (Uint32 i = 0; i < indicationProviders.size(); i++)
6911     {
6912         //
6913         //  Create the create subscription request
6914         //
6915        CIMCreateSubscriptionRequestMessage * request =
6916             new CIMCreateSubscriptionRequestMessage(
6917                 XmlWriter::getNextMessageId(),
6918                 nameSpace,
6919                 subscription,
6920                 indicationProviders[i].classList,
6921                 propertyList,
6922                 repeatNotificationPolicy,
6923                 query,
6924                 QueueIdStack(_providerManager, getQueueId()),
6925                 authType,
6926                 userName);
6927
6928         //
6929         //  Store a copy of the request in the operation aggregate instance
6930         //
6931         CIMCreateSubscriptionRequestMessage * requestCopy =
6932             new CIMCreateSubscriptionRequestMessage(*request);
6933         requestCopy->operationContext.insert(ProviderIdContainer(
6934             indicationProviders[i].providerModule
6935             ,indicationProviders[i].provider
6936 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
6937             ,indicationProviders[i].isRemoteNameSpace
6938             ,indicationProviders[i].remoteInfo
6939 #endif
6940             ));
6941         operationAggregate->appendRequest(requestCopy);
6942         request->operationContext.insert(ProviderIdContainer(
6943             indicationProviders[i].providerModule
6944             ,indicationProviders[i].provider
6945 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
6946             ,indicationProviders[i].isRemoteNameSpace
6947             ,indicationProviders[i].remoteInfo
6948 #endif
6949             ));
6950         request->operationContext.insert(
6951             SubscriptionInstanceContainer(subscription));
6952         request->operationContext.insert(
6953             SubscriptionFilterConditionContainer(condition,queryLanguage));
6954         request->operationContext.insert(
6955             SubscriptionFilterQueryContainer(query,queryLanguage,nameSpace));
6956         request->operationContext.insert(IdentityContainer(userName));
6957         request->operationContext.set(
6958             ContentLanguageListContainer(contentLangs));
6959         request->operationContext.set(AcceptLanguageListContainer(acceptLangs));
6960
6961         AsyncOpNode * op = this->get_op();
6962
6963         AsyncLegacyOperationStart * async_req =
6964             new AsyncLegacyOperationStart(
6965                 op,
6966                 _providerManager,
6967                 request);
6968
6969         SendAsync(
6970             op,
6971             _providerManager,
6972             IndicationService::_aggregationCallBack,
6973             this,
6974             operationAggregate);
6975
6976 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
6977        // Release AutomicInt if atleast one request is sent for aggregation.
6978        counter.release();
6979 #endif
6980     }
6981
6982     PEG_METHOD_EXIT();
6983 }
6984
6985 Array<ProviderClassList> IndicationService::_sendWaitCreateRequests(
6986     const Array<ProviderClassList>& indicationProviders,
6987     const CIMNamespaceName& nameSpace,
6988     const CIMPropertyList& propertyList,
6989     const String& condition,
6990     const String& query,
6991     const String& queryLanguage,
6992     const CIMInstance& subscription,
6993     const AcceptLanguageList& acceptLangs,
6994     const ContentLanguageList& contentLangs,
6995     const String& userName,
6996     const String& authType)
6997 {
6998     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
6999         "IndicationService::_sendWaitCreateRequests");
7000
7001     CIMValue propValue;
7002     Uint16 repeatNotificationPolicy;
7003     Array<ProviderClassList> acceptedProviders;
7004     acceptedProviders.clear();
7005
7006     // If there are no providers to accept the subscription, just return
7007     if (indicationProviders.size() == 0)
7008     {
7009         PEG_METHOD_EXIT();
7010         return acceptedProviders;
7011     }
7012
7013     //
7014     //  Get repeat notification policy value from subscription instance
7015     //
7016     propValue = subscription.getProperty(
7017         subscription.findProperty(
7018             _PROPERTY_REPEATNOTIFICATIONPOLICY)).getValue();
7019     propValue.get(repeatNotificationPolicy);
7020
7021     //
7022     //  Send Create request to each provider
7023     //
7024     for (Uint32 i = 0; i < indicationProviders.size(); i++)
7025     {
7026         //
7027         //  Create the create subscription request
7028         //
7029         CIMCreateSubscriptionRequestMessage * request =
7030             new CIMCreateSubscriptionRequestMessage(
7031                 XmlWriter::getNextMessageId(),
7032                 nameSpace,
7033                 subscription,
7034                 indicationProviders[i].classList,
7035                 propertyList,
7036                 repeatNotificationPolicy,
7037                 query,
7038                 QueueIdStack(_providerManager, getQueueId()),
7039                 authType,
7040                 userName);
7041
7042         //
7043         //  Set operation context
7044         //
7045         request->operationContext.insert(ProviderIdContainer(
7046             indicationProviders[i].providerModule
7047             ,indicationProviders[i].provider
7048 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
7049             ,indicationProviders[i].isRemoteNameSpace
7050             ,indicationProviders[i].remoteInfo
7051 #endif
7052             ));
7053         request->operationContext.insert(
7054             SubscriptionInstanceContainer(subscription));
7055         request->operationContext.insert(
7056             SubscriptionFilterConditionContainer(condition,queryLanguage));
7057         request->operationContext.insert(
7058             SubscriptionFilterQueryContainer(query,queryLanguage,nameSpace));
7059         request->operationContext.insert(IdentityContainer(userName));
7060         request->operationContext.set(
7061             ContentLanguageListContainer(contentLangs));
7062         request->operationContext.set(AcceptLanguageListContainer(acceptLangs));
7063
7064         AsyncLegacyOperationStart * asyncRequest =
7065             new AsyncLegacyOperationStart(
7066                 0,
7067                 _providerManager,
7068                 request);
7069
7070         AsyncReply * asyncReply = SendWait(asyncRequest);
7071
7072         CIMCreateSubscriptionResponseMessage * response =
7073             reinterpret_cast<CIMCreateSubscriptionResponseMessage *>(
7074                 (static_cast<AsyncLegacyOperationResult *>(
7075                     asyncReply))->get_result());
7076
7077         if (response->cimException.getCode() == CIM_ERR_SUCCESS)
7078         {
7079             acceptedProviders.append(indicationProviders[i]);
7080 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
7081             _providerIndicationCountTable.insertEntry(
7082                 indicationProviders[i].provider);
7083 #endif
7084         }
7085         else
7086         {
7087             //
7088             //  Provider rejected the subscription
7089             //
7090             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL2,
7091                 "Provider (%s) rejected create subscription: %s",
7092                 (const char*)indicationProviders[i].provider.getPath()
7093                        .toString().getCString(),
7094                 (const char*)response->cimException.getMessage().getCString()));
7095         }
7096
7097         delete response;
7098         delete asyncRequest;
7099         delete asyncReply;
7100     }  //  for each indication provider
7101
7102     PEG_METHOD_EXIT();
7103     return acceptedProviders;
7104 }
7105
7106 void IndicationService::_sendWaitModifyRequests(
7107     const Array<ProviderClassList>& indicationProviders,
7108      const CIMNamespaceName& nameSpace,
7109      const CIMPropertyList& propertyList,
7110      const String& condition,
7111      const String& query,
7112      const String& queryLanguage,
7113      const CIMInstance& subscription,
7114      const AcceptLanguageList& acceptLangs,
7115      const ContentLanguageList& contentLangs,
7116      const String& userName,
7117      const String& authType)
7118 {
7119     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
7120         "IndicationService::_sendWaitModifyRequests");
7121
7122     CIMValue propValue;
7123     Uint16 repeatNotificationPolicy;
7124
7125     // If there are no providers to accept the subscription update, just return
7126     if (indicationProviders.size() == 0)
7127     {
7128         PEG_METHOD_EXIT();
7129         return;
7130     }
7131
7132     //
7133     //  Get repeat notification policy value from subscription instance
7134     //
7135     propValue = subscription.getProperty(
7136         subscription.findProperty(
7137             _PROPERTY_REPEATNOTIFICATIONPOLICY)).getValue();
7138     propValue.get(repeatNotificationPolicy);
7139
7140     //
7141     //  Send Modify request to each provider
7142     //
7143     for (Uint32 i = 0; i < indicationProviders.size(); i++)
7144     {
7145         CIMModifySubscriptionRequestMessage * request =
7146             new CIMModifySubscriptionRequestMessage(
7147                 XmlWriter::getNextMessageId(),
7148                 nameSpace,
7149                 subscription,
7150                 indicationProviders[i].classList,
7151                 propertyList,
7152                 repeatNotificationPolicy,
7153                 query,
7154                 QueueIdStack(_providerManager, getQueueId()),
7155                 authType,
7156                 userName);
7157
7158         //
7159         //  Set operation context
7160         //
7161         request->operationContext.insert(ProviderIdContainer(
7162             indicationProviders[i].providerModule
7163             ,indicationProviders[i].provider
7164 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
7165             ,indicationProviders[i].isRemoteNameSpace
7166             ,indicationProviders[i].remoteInfo
7167 #endif
7168             ));
7169         request->operationContext.insert(
7170             SubscriptionInstanceContainer(subscription));
7171         request->operationContext.insert(
7172             SubscriptionFilterConditionContainer(condition,queryLanguage));
7173         request->operationContext.insert(
7174             SubscriptionFilterQueryContainer(query,queryLanguage,nameSpace));
7175         request->operationContext.insert(IdentityContainer(userName));
7176         request->operationContext.set(
7177             ContentLanguageListContainer(contentLangs));
7178         request->operationContext.set(AcceptLanguageListContainer(acceptLangs));
7179
7180         AsyncLegacyOperationStart * asyncRequest =
7181             new AsyncLegacyOperationStart(
7182                 0,
7183                 _providerManager,
7184                 request);
7185
7186         AsyncReply * asyncReply = SendWait(asyncRequest);
7187
7188         CIMModifySubscriptionResponseMessage * response =
7189             reinterpret_cast<CIMModifySubscriptionResponseMessage *>(
7190                 (static_cast<AsyncLegacyOperationResult *>(
7191                     asyncReply))->get_result());
7192
7193         if (!(response->cimException.getCode() == CIM_ERR_SUCCESS))
7194         {
7195             //
7196             //  Provider rejected the subscription
7197             //
7198             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL2,
7199                 "Provider (%s) rejected modify subscription: %s",
7200                 (const char*)indicationProviders[i].provider.getPath()
7201                        .toString().getCString(),
7202                 (const char*)response->cimException.getMessage().getCString()));
7203         }
7204
7205         delete response;
7206         delete asyncRequest;
7207         delete asyncReply;
7208     }  //  for each indication provider
7209
7210     PEG_METHOD_EXIT();
7211 }
7212
7213 void IndicationService::_sendAsyncDeleteRequests(
7214     const Array<ProviderClassList>& indicationProviders,
7215     const CIMNamespaceName& nameSpace,
7216     const CIMInstance& subscription,
7217     const AcceptLanguageList& acceptLangs,
7218     const ContentLanguageList& contentLangs,
7219     const CIMRequestMessage * origRequest,
7220     const Array<CIMName>& indicationSubclasses,
7221     const String& userName,
7222     const String& authType)
7223 {
7224     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
7225         "IndicationService::_sendAsyncDeleteRequests");
7226
7227     // If there are no providers to delete the subscription, just return
7228     if (indicationProviders.size() == 0)
7229     {
7230         PEG_METHOD_EXIT();
7231         return;
7232     }
7233
7234 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
7235     _asyncRequestsPending++;
7236     AutoPtr<AtomicInt, DecAtomicInt> counter(&_asyncRequestsPending);
7237 #endif
7238
7239     //
7240     //  Update subscription hash tables
7241     //
7242     _subscriptionTable->removeSubscription(
7243         subscription,
7244         indicationSubclasses,
7245         nameSpace,
7246         indicationProviders);
7247
7248     CIMRequestMessage * aggRequest = 0;
7249
7250     if (origRequest == 0)
7251     {
7252         //
7253         //  Delete a referencing or expired subscription -- no request
7254         //  associated with this delete
7255         //
7256         aggRequest = 0;
7257     }
7258     else
7259     {
7260         //
7261         //  Delete Instance or Modify Instance
7262         //
7263         switch (origRequest->getType())
7264         {
7265             case CIM_DELETE_INSTANCE_REQUEST_MESSAGE:
7266             {
7267                 CIMDeleteInstanceRequestMessage * request =
7268                     (CIMDeleteInstanceRequestMessage *) origRequest;
7269                 CIMDeleteInstanceRequestMessage * requestCopy =
7270                     new CIMDeleteInstanceRequestMessage(*request);
7271                 aggRequest = requestCopy;
7272                 break;
7273             }
7274
7275             case CIM_MODIFY_INSTANCE_REQUEST_MESSAGE:
7276             {
7277                 CIMModifyInstanceRequestMessage * request =
7278                     (CIMModifyInstanceRequestMessage *) origRequest;
7279                 CIMModifyInstanceRequestMessage * requestCopy =
7280                     new CIMModifyInstanceRequestMessage(*request);
7281                 aggRequest = requestCopy;
7282                 break;
7283             }
7284
7285             default:
7286             {
7287                 PEG_TRACE((TRC_INDICATION_SERVICE,Tracer::LEVEL1,
7288                     "Unexpected origRequest type %s "
7289                     "in _sendAsyncDeleteRequests",
7290                     MessageTypeToString(origRequest->getType())));
7291                 PEGASUS_ASSERT(false);
7292                 break;
7293             }
7294         }
7295     }
7296
7297     //
7298     //  Create an aggregate object for the delete subscription requests
7299     //
7300     IndicationOperationAggregate * operationAggregate =
7301         new IndicationOperationAggregate(aggRequest, indicationSubclasses);
7302     operationAggregate->setNumberIssued(indicationProviders.size());
7303
7304     //
7305     //  Send Delete request to each provider
7306     //
7307     for (Uint32 i = 0; i < indicationProviders.size(); i++)
7308     {
7309         CIMDeleteSubscriptionRequestMessage * request =
7310             new CIMDeleteSubscriptionRequestMessage(
7311                 XmlWriter::getNextMessageId(),
7312                 nameSpace,
7313                 subscription,
7314                 indicationProviders[i].classList,
7315                 QueueIdStack(_providerManager, getQueueId()),
7316                 authType,
7317                 userName);
7318
7319         //
7320         //  Store a copy of the request in the operation aggregate instance
7321         //
7322         CIMDeleteSubscriptionRequestMessage * requestCopy =
7323             new CIMDeleteSubscriptionRequestMessage(*request);
7324         requestCopy->operationContext.insert(ProviderIdContainer(
7325             indicationProviders[i].providerModule
7326             ,indicationProviders[i].provider
7327 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
7328             ,indicationProviders[i].isRemoteNameSpace
7329             ,indicationProviders[i].remoteInfo
7330 #endif
7331              ));
7332         operationAggregate->appendRequest(requestCopy);
7333         request->operationContext.insert(ProviderIdContainer(
7334             indicationProviders[i].providerModule
7335             ,indicationProviders[i].provider
7336 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
7337             ,indicationProviders[i].isRemoteNameSpace
7338             ,indicationProviders[i].remoteInfo
7339 #endif
7340             ));
7341
7342         request->operationContext.insert(
7343             SubscriptionInstanceContainer(subscription));
7344         request->operationContext.insert(IdentityContainer(userName));
7345         request->operationContext.set(
7346             ContentLanguageListContainer(contentLangs));
7347         request->operationContext.set(AcceptLanguageListContainer(acceptLangs));
7348
7349         AsyncOpNode * op = this->get_op();
7350
7351         AsyncLegacyOperationStart * async_req =
7352             new AsyncLegacyOperationStart(
7353                 op,
7354                 _providerManager,
7355                 request);
7356
7357         SendAsync(
7358             op,
7359             _providerManager,
7360             IndicationService::_aggregationCallBack,
7361             this,
7362             operationAggregate);
7363
7364 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
7365        // Release AutomicInt if atleast one request is sent for aggregation.
7366        counter.release();
7367 #endif
7368     }
7369
7370     PEG_METHOD_EXIT();
7371 }
7372
7373 void IndicationService::_sendWaitDeleteRequests(
7374     const Array<ProviderClassList>& indicationProviders,
7375     const CIMNamespaceName& nameSpace,
7376     const CIMInstance& subscription,
7377     const AcceptLanguageList& acceptLangs,
7378     const ContentLanguageList& contentLangs,
7379     const String& userName,
7380     const String& authType)
7381 {
7382     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
7383         "IndicationService::_sendWaitDeleteRequests");
7384
7385     // If there are no providers to delete the subscription, just return
7386     if (indicationProviders.size() == 0)
7387     {
7388         PEG_METHOD_EXIT();
7389         return;
7390     }
7391
7392     //
7393     //  Send Delete request to each provider
7394     //
7395     for (Uint32 i = 0; i < indicationProviders.size(); i++)
7396     {
7397         CIMDeleteSubscriptionRequestMessage * request =
7398             new CIMDeleteSubscriptionRequestMessage(
7399                 XmlWriter::getNextMessageId(),
7400                 nameSpace,
7401                 subscription,
7402                 indicationProviders[i].classList,
7403                 QueueIdStack(_providerManager, getQueueId()),
7404                 authType,
7405                 userName);
7406
7407         //
7408         //  Set operation context
7409         //
7410         request->operationContext.insert(ProviderIdContainer(
7411             indicationProviders[i].providerModule
7412             ,indicationProviders[i].provider
7413 #ifdef PEGASUS_ENABLE_REMOTE_CMPI
7414             ,indicationProviders[i].isRemoteNameSpace
7415             ,indicationProviders[i].remoteInfo
7416 #endif
7417             ));
7418         request->operationContext.insert(
7419             SubscriptionInstanceContainer(subscription));
7420         request->operationContext.insert(IdentityContainer(userName));
7421         request->operationContext.set(
7422             ContentLanguageListContainer(contentLangs));
7423         request->operationContext.set(AcceptLanguageListContainer(acceptLangs));
7424
7425         AsyncLegacyOperationStart * asyncRequest =
7426             new AsyncLegacyOperationStart(
7427                 0,
7428                 _providerManager,
7429                 request);
7430
7431         AsyncReply * asyncReply = SendWait(asyncRequest);
7432
7433         CIMDeleteSubscriptionResponseMessage * response =
7434             reinterpret_cast<CIMDeleteSubscriptionResponseMessage *>(
7435                 (static_cast<AsyncLegacyOperationResult *>(
7436                     asyncReply))->get_result());
7437
7438         if (!(response->cimException.getCode() == CIM_ERR_SUCCESS))
7439         {
7440             //
7441             //  Provider rejected the subscription
7442             //
7443             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL2,
7444                 "Provider (%s) rejected delete subscription: %s",
7445                 (const char*)indicationProviders[i].provider.getPath()
7446                        .toString().getCString(),
7447                 (const char*)response->cimException.getMessage().getCString()));
7448         }
7449
7450         delete response;
7451         delete asyncRequest;
7452         delete asyncReply;
7453     }  //  for each indication provider
7454
7455     PEG_METHOD_EXIT();
7456 }
7457
7458 void IndicationService::_aggregationCallBack(
7459     AsyncOpNode * op,
7460     MessageQueue * q,
7461     void * userParameter)
7462 {
7463     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
7464         "IndicationService::_aggregationCallBack");
7465
7466     IndicationService * service = static_cast<IndicationService *>(q);
7467
7468     AsyncRequest * asyncRequest =
7469         static_cast<AsyncRequest *>(op->removeRequest());
7470     AsyncReply * asyncReply = static_cast<AsyncReply *>(op->removeResponse());
7471
7472     IndicationOperationAggregate * operationAggregate =
7473         reinterpret_cast<IndicationOperationAggregate *>(userParameter);
7474     PEGASUS_ASSERT(operationAggregate != 0);
7475
7476     CIMResponseMessage * response = 0;
7477     MessageType msgType = asyncReply->getType();
7478     PEGASUS_ASSERT((msgType == ASYNC_ASYNC_LEGACY_OP_RESULT) ||
7479                    (msgType == ASYNC_ASYNC_MODULE_OP_RESULT));
7480
7481     if (msgType == ASYNC_ASYNC_LEGACY_OP_RESULT)
7482     {
7483         response = reinterpret_cast<CIMResponseMessage *>(
7484             (static_cast<AsyncLegacyOperationResult *>(
7485                 asyncReply))->get_result());
7486     }
7487     else if (msgType == ASYNC_ASYNC_MODULE_OP_RESULT)
7488     {
7489         response = reinterpret_cast<CIMResponseMessage *>(
7490             (static_cast<AsyncModuleOperationResult *>(
7491                 asyncReply))->get_result());
7492     }
7493
7494     PEGASUS_ASSERT(response != 0);
7495
7496     delete asyncRequest;
7497     delete asyncReply;
7498     service->return_op(op);
7499
7500     Boolean isDoneAggregation = operationAggregate->appendResponse(response);
7501     if (isDoneAggregation)
7502     {
7503         service->_handleOperationResponseAggregation(operationAggregate);
7504 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
7505         service->_asyncRequestsPending--;
7506 #endif
7507     }
7508
7509     PEG_METHOD_EXIT();
7510 }
7511
7512 void IndicationService::_handleOperationResponseAggregation(
7513     IndicationOperationAggregate * operationAggregate)
7514 {
7515     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
7516         "IndicationService::_handleOperationResponseAggregation");
7517
7518     switch (operationAggregate->getRequest(0)->getType())
7519     {
7520         case CIM_CREATE_SUBSCRIPTION_REQUEST_MESSAGE:
7521         {
7522             _handleCreateResponseAggregation(operationAggregate);
7523             break;
7524         }
7525
7526         case CIM_DELETE_SUBSCRIPTION_REQUEST_MESSAGE:
7527         {
7528             _handleDeleteResponseAggregation(operationAggregate);
7529             break;
7530         }
7531
7532         default:
7533         {
7534             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL1,
7535                 "Unexpected request type %s "
7536                 "in _handleOperationResponseAggregation",
7537                 MessageTypeToString(
7538                     operationAggregate->getRequest(0)->getType())));
7539             PEGASUS_ASSERT(false);
7540             break;
7541         }
7542     }
7543
7544     //
7545     //  Requests and responses are deleted in destructor
7546     //
7547     delete operationAggregate;
7548
7549     PEG_METHOD_EXIT();
7550 }
7551
7552 void IndicationService::_handleCreateResponseAggregation(
7553     IndicationOperationAggregate * operationAggregate)
7554 {
7555     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
7556         "IndicationService::_handleCreateResponseAggregation");
7557
7558     Array<ProviderClassList> acceptedProviders;
7559     CIMObjectPath instanceRef;
7560     CIMException cimException;
7561
7562     //
7563     //  Examine provider responses
7564     //
7565     acceptedProviders.clear();
7566     for (Uint32 i = 0; i < operationAggregate->getNumberResponses(); i++)
7567     {
7568         //
7569         //  Find provider from which response was sent
7570         //
7571         CIMResponseMessage * response = operationAggregate->getResponse(i);
7572         ProviderClassList provider = operationAggregate->findProvider(
7573             response->messageId);
7574         if (response->cimException.getCode() == CIM_ERR_SUCCESS)
7575         {
7576             //
7577             //  If response is SUCCESS, provider accepted the subscription
7578             //  Add provider to list of providers that accepted subscription
7579             //
7580             acceptedProviders.append(provider);
7581 #ifdef PEGASUS_ENABLE_INDICATION_COUNT
7582             _providerIndicationCountTable.insertEntry(provider.provider);
7583 #endif
7584         }
7585         else
7586         {
7587             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL2,
7588                 "Provider (%s) rejected create subscription: %s",
7589                 (const char*)
7590                      provider.provider.getPath().toString().getCString(),
7591                 (const char*)response->cimException.getMessage().getCString()));
7592         }
7593     }
7594
7595     CIMCreateSubscriptionRequestMessage * request =
7596         (CIMCreateSubscriptionRequestMessage *)
7597             operationAggregate->getRequest(0);
7598
7599     if (operationAggregate->getOrigType() ==
7600         CIM_CREATE_INSTANCE_REQUEST_MESSAGE)
7601     {
7602         instanceRef = request->subscriptionInstance.getPath();
7603     }
7604
7605
7606 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
7607     if (operationAggregate->getOrigRequest() == 0)
7608     {
7609             //
7610             // There is no request associated with the aggregation object.
7611             // This request must have been sent during the indication
7612             // service initialization because of timeout specified.
7613             //
7614             _updateAcceptedSubscription(
7615                 request->subscriptionInstance,
7616                 acceptedProviders,
7617                 operationAggregate->getIndicationSubclasses(),
7618                 request->nameSpace);
7619     }
7620     else
7621 #endif
7622     if (acceptedProviders.size() == 0)
7623     {
7624         //
7625         //  No providers accepted this subscription
7626         //
7627         if (operationAggregate->requiresResponse())
7628         {
7629             //
7630             //  For Create Instance or Modify Instance request, set CIM
7631             //  exception for response
7632             //
7633             cimException = PEGASUS_CIM_EXCEPTION_L(CIM_ERR_NOT_SUPPORTED,
7634                 MessageLoaderParms(
7635                     "IndicationService.IndicationService._MSG_NOT_ACCEPTED",
7636                     "No providers accepted the subscription."));
7637         }
7638     }
7639     else
7640     {
7641         //
7642         //  At least one provider accepted the subscription
7643         //
7644         if (operationAggregate->getOrigType() ==
7645             CIM_CREATE_INSTANCE_REQUEST_MESSAGE)
7646         {
7647             //
7648             //  Create Instance -- create the instance in the repository
7649             //
7650             CIMCreateInstanceRequestMessage * origRequest =
7651                 (CIMCreateInstanceRequestMessage *)
7652                     operationAggregate->getOrigRequest();
7653
7654             CIMInstance instance;
7655             try
7656             {
7657                 instanceRef = _subscriptionRepository->createInstance(
7658                     request->subscriptionInstance, origRequest->nameSpace,
7659                     ((IdentityContainer)origRequest->operationContext.get
7660                         (IdentityContainer::NAME)).getUserName(),
7661                     ((AcceptLanguageListContainer)request->operationContext.get
7662                         (AcceptLanguageListContainer::NAME)).getLanguages(),
7663                     ((ContentLanguageListContainer)request->operationContext.get
7664                         (ContentLanguageListContainer::NAME)).getLanguages(),
7665                         true);
7666                 instanceRef.setNameSpace(
7667                     request->subscriptionInstance.getPath().getNameSpace());
7668                 instance = _subscriptionRepository->getInstance(
7669                     origRequest->nameSpace, instanceRef);
7670                 instance.setPath(instanceRef);
7671             }
7672             catch (CIMException& exception)
7673             {
7674                 cimException = exception;
7675             }
7676             catch (Exception& exception)
7677             {
7678                 cimException = PEGASUS_CIM_EXCEPTION(
7679                     CIM_ERR_FAILED, exception.getMessage());
7680             }
7681
7682             if (cimException.getCode() == CIM_ERR_SUCCESS)
7683             {
7684                 //
7685                 //  Insert entries into the subscription hash tables
7686                 //
7687                 _subscriptionTable->insertSubscription(
7688                     instance,
7689                     acceptedProviders,
7690                     operationAggregate->getIndicationSubclasses(),
7691                     request->nameSpace);
7692
7693             }
7694         }
7695         else  //  CIM_MODIFY_INSTANCE_REQUEST_MESSAGE
7696         {
7697
7698             PEGASUS_ASSERT(operationAggregate->getOrigType() ==
7699                 CIM_MODIFY_INSTANCE_REQUEST_MESSAGE);
7700             //
7701             //  Insert entries into the subscription hash tables
7702             //
7703             _subscriptionTable->insertSubscription(
7704                 request->subscriptionInstance,
7705                 acceptedProviders,
7706                 operationAggregate->getIndicationSubclasses(),
7707                 request->nameSpace);
7708         }
7709     }
7710
7711     // If subscription could not be created, cancel create subscription request
7712     // or commit create subscription request if subscription was created.
7713     if (instanceRef.getKeyBindings().size())
7714     {
7715         if (cimException.getCode() != CIM_ERR_SUCCESS)
7716         {
7717             _subscriptionRepository->cancelCreateSubscription(instanceRef);
7718         }
7719         else
7720         {
7721             _subscriptionRepository->commitCreateSubscription(instanceRef);
7722         }
7723     }
7724
7725     //
7726     //  For Create Instance or Modify Instance request, send response
7727     //
7728     if (operationAggregate->requiresResponse())
7729     {
7730         if (operationAggregate->getOrigType() ==
7731             CIM_CREATE_INSTANCE_REQUEST_MESSAGE)
7732         {
7733             // Note: don't need to set Content-language in the response
7734             CIMCreateInstanceResponseMessage* response =
7735                 dynamic_cast<CIMCreateInstanceResponseMessage*>(
7736                     operationAggregate->getOrigRequest()->buildResponse());
7737             PEGASUS_ASSERT(response != 0);
7738             response->cimException = cimException;
7739             response->instanceName = instanceRef;
7740             _enqueueResponse(operationAggregate->getOrigRequest(), response);
7741         }
7742
7743         else  //  CIM_MODIFY_INSTANCE_REQUEST_MESSAGE
7744         {
7745             PEGASUS_ASSERT(operationAggregate->getOrigType () ==
7746                 CIM_MODIFY_INSTANCE_REQUEST_MESSAGE);
7747             // l10n
7748             // Note: don't need to set Content-language in the response
7749             //
7750             CIMResponseMessage * response =
7751                 operationAggregate->getOrigRequest()->buildResponse();
7752             response->cimException = cimException;
7753             _enqueueResponse(operationAggregate->getOrigRequest(), response);
7754         }
7755     }
7756
7757     PEG_METHOD_EXIT();
7758 }
7759
7760 void IndicationService::_handleDeleteResponseAggregation(
7761     IndicationOperationAggregate * operationAggregate)
7762 {
7763     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
7764         "IndicationService::_handleDeleteResponseAggregation");
7765
7766     CIMException cimException;
7767     Array<ProviderClassList> checkProviders;
7768
7769     //
7770     //  Examine provider responses
7771     //
7772     for (Uint32 i = 0; i < operationAggregate->getNumberResponses(); i++)
7773     {
7774         //
7775         //  Find provider from which response was sent and add to list
7776         //
7777         CIMResponseMessage * response = operationAggregate->getResponse(i);
7778         ProviderClassList provider = operationAggregate->findProvider(
7779             response->messageId);
7780         checkProviders.append(provider);
7781
7782         //
7783         //  If response is not SUCCESS, provider rejected the delete
7784         //
7785         if (response->cimException.getCode() != CIM_ERR_SUCCESS)
7786         {
7787             //
7788             //  Log a trace message
7789             //
7790             PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL2,
7791                 "Provider (%s) rejected delete subscription: %s",
7792                 (const char*)
7793                      provider.provider.getPath().toString().getCString(),
7794                 (const char*)response->cimException.getMessage().getCString()));
7795         }
7796     }
7797
7798     //
7799     //  For Delete Instance or Modify Instance request, send response
7800     //
7801     if (operationAggregate->requiresResponse())
7802     {
7803         CIMResponseMessage * response;
7804         if (operationAggregate->getOrigType() ==
7805             CIM_DELETE_INSTANCE_REQUEST_MESSAGE)
7806         {
7807             // l10n
7808             // Note: don't need to set Content-language in the response
7809             response = operationAggregate->getOrigRequest()->buildResponse();
7810             response->cimException = cimException;
7811         }
7812
7813         else  //  CIM_MODIFY_INSTANCE_REQUEST_MESSAGE
7814         {
7815             PEGASUS_ASSERT(operationAggregate->getOrigType() ==
7816                 CIM_MODIFY_INSTANCE_REQUEST_MESSAGE);
7817             // l10n
7818             // Note: don't need to set Content-language in the response
7819             response = operationAggregate->getOrigRequest()->buildResponse();
7820             response->cimException = cimException;
7821         }
7822
7823         _enqueueResponse(operationAggregate->getOrigRequest(), response);
7824     }
7825
7826     PEG_METHOD_EXIT();
7827 }
7828
7829 CIMInstance IndicationService::_createAlertInstance(
7830     const CIMName& alertClassName,
7831     const Array<CIMInstance>& subscriptions)
7832 {
7833     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
7834         "IndicationService::_createAlertInstance");
7835
7836     CIMInstance indicationInstance(alertClassName);
7837
7838     //
7839     //  Add property values for all required properties of CIM_AlertIndication
7840     //
7841     indicationInstance.addProperty(
7842         CIMProperty(_PROPERTY_ALERTTYPE, CIMValue((Uint16) _TYPE_OTHER)));
7843     //
7844     //  ATTN: what should Other Alert Type value be??
7845     //  Currently using Alert class name
7846     //
7847     indicationInstance.addProperty(
7848         CIMProperty(_PROPERTY_OTHERALERTTYPE, alertClassName.getString()));
7849
7850     indicationInstance.addProperty(
7851         CIMProperty(_PROPERTY_PERCEIVEDSEVERITY,
7852             CIMValue((Uint16) _SEVERITY_WARNING)));
7853     //
7854     //  ATTN: what should Probable Cause value be??
7855     //  Currently using Unknown
7856     //
7857     indicationInstance.addProperty(
7858         CIMProperty(_PROPERTY_PROBABLECAUSE,
7859             CIMValue((Uint16) _CAUSE_UNKNOWN)));
7860
7861     //
7862     //  Add properties specific to each alert class
7863     //  ATTN: update once alert classes have been defined
7864     //  NB: for _CLASS_NO_PROVIDER_ALERT and _CLASS_PROVIDER_TERMINATED_ALERT,
7865     //  one of the properties will be a list of affected subscriptions
7866     //  It is for that reason that subscriptions is passed in as a parameter
7867     //
7868     if (alertClassName.equal(_CLASS_CIMOM_SHUTDOWN_ALERT))
7869     {
7870     }
7871     else if (alertClassName.equal(_CLASS_NO_PROVIDER_ALERT))
7872     {
7873     }
7874     else if (alertClassName.equal(_CLASS_PROVIDER_TERMINATED_ALERT))
7875     {
7876     }
7877
7878     PEG_METHOD_EXIT();
7879     return indicationInstance;
7880 }
7881
7882
7883 #if 0
7884 void IndicationService::_sendAlertsCallBack(AsyncOpNode *op,
7885     MessageQueue *q,
7886     void *parm)
7887 {
7888     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
7889         "IndicationService::_sendAlertsCallBack");
7890
7891    IndicationService *service =
7892       static_cast<IndicationService *>(q);
7893    CIMInstance *_handler =
7894       reinterpret_cast<CIMInstance *>(parm);
7895
7896    AsyncRequest *asyncRequest = static_cast<AsyncRequest *>(op->get_request());
7897    AsyncReply *asyncReply = static_cast<AsyncReply *>(op->get_response());
7898    CIMRequestMessage *request = reinterpret_cast<CIMRequestMessage *>(
7899       (static_cast<AsyncLegacyOperationStart *>(asyncRequest))->get_action());
7900
7901    CIMHandleIndicationResponseMessage* response =
7902       reinterpret_cast<CIMHandleIndicationResponseMessage *>(
7903           (static_cast<AsyncLegacyOperationResult *>(
7904               asyncReply))->get_result());
7905
7906    PEGASUS_ASSERT(response != 0);
7907    if (response->cimException.getCode() == CIM_ERR_SUCCESS)
7908    {
7909    }
7910    else
7911    {
7912    }
7913
7914    //
7915    //  ATTN: Check for return value indicating invalid queue ID
7916    //  If received, need to find Handler Manager Service queue ID
7917    //  again
7918    //
7919
7920 // << Mon Jul 15 09:59:16 2002 mdd >> handler is allocated as an element in
7921 // an array, don't delete here.
7922 //   delete _handler;
7923    delete request;
7924    delete response;
7925    delete asyncRequest;
7926    delete asyncReply;
7927    op->release();
7928    service->return_op(op);
7929
7930     PEG_METHOD_EXIT();
7931 }
7932
7933
7934 void IndicationService::_sendAlerts(
7935     const Array<CIMInstance>& subscriptions,
7936     /* const */ CIMInstance& alertInstance)
7937 {
7938     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "IndicationService::_sendAlerts");
7939
7940     CIMInstance current;
7941
7942     PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
7943         "Sending alert: %s",
7944         (const char*)alertInstance.getClassName().getString().getCString()));
7945
7946     //
7947     //  Get list of unique handler instances for all subscriptions in list
7948     //
7949     for (Uint32 i = 0; i < subscriptions.size(); i++)
7950     {
7951         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
7952             "Alert subscription: %s",
7953             (const char*)subscriptions[i].getPath().toString().getCString()));
7954
7955         //
7956         //  Get handler instance
7957         //
7958         current = _subscriptionRepository->getHandler(subscriptions[i]);
7959
7960     // ATTN: For the handlers which do not need subscription instance
7961     // need to check duplicate alter
7962
7963             //
7964             //  Send handle indication request to the handler
7965             //
7966             CIMHandleIndicationRequestMessage * handler_request =
7967                 new CIMHandleIndicationRequestMessage(
7968                     XmlWriter::getNextMessageId(),
7969                     current.getPath().getNameSpace(),
7970                     current,
7971             subscriptions[i],
7972                     alertInstance,
7973                     QueueIdStack(_handlerService, getQueueId()));
7974
7975             AsyncOpNode* op = this->get_op();
7976
7977             AsyncLegacyOperationStart *async_req =
7978                 new AsyncLegacyOperationStart(
7979                     op,
7980                     _handlerService,
7981                     handler_request,
7982                     _queueId);
7983
7984             SendAsync(op,
7985                   _handlerService,
7986                   IndicationService::_sendAlertsCallBack,
7987                   this,
7988                   (void *)&current);
7989
7990     }
7991
7992     PEG_METHOD_EXIT();
7993 }
7994 #endif
7995
7996 void IndicationService::sendSubscriptionInitComplete()
7997 {
7998     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
7999         "IndicationService::sendSubscriptionInitComplete");
8000
8001     if (_enabledState == _ENABLEDSTATE_DISABLED)
8002     {
8003         PEG_METHOD_EXIT();
8004         return;
8005     }
8006     //
8007     //  Create the Subscription Init Complete request
8008     //
8009     CIMSubscriptionInitCompleteRequestMessage * request =
8010         new CIMSubscriptionInitCompleteRequestMessage(
8011             XmlWriter::getNextMessageId(),
8012             QueueIdStack(_providerManager, getQueueId()));
8013
8014     //
8015     //  Send Subscription Initialization Complete request to provider manager
8016     //  Provider Manager calls providers' enableIndications method
8017     //
8018     AsyncLegacyOperationStart * asyncRequest =
8019         new AsyncLegacyOperationStart(
8020             0,
8021             _providerManager,
8022             request);
8023
8024     AutoPtr<AsyncReply> asyncReply(SendWait(asyncRequest));
8025     //
8026     //  Note: the response does not contain interesting data
8027     //
8028     delete asyncRequest;
8029
8030     PEG_METHOD_EXIT();
8031 }
8032
8033 Boolean IndicationService::_getCreator(
8034     const CIMInstance& instance,
8035     String& creator) const
8036 {
8037     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "IndicationService::_getCreator");
8038
8039     Uint32 creatorIndex = instance.findProperty(
8040         PEGASUS_PROPERTYNAME_INDSUB_CREATOR);
8041     if (creatorIndex != PEG_NOT_FOUND)
8042     {
8043         CIMValue creatorValue = instance.getProperty(creatorIndex).getValue();
8044         if (creatorValue.isNull())
8045         {
8046             PEG_TRACE_CSTRING(TRC_INDICATION_SERVICE,Tracer::LEVEL1,
8047                 "Null Subscription Creator property value");
8048
8049             //
8050             //  This is a corrupted/invalid instance
8051             //
8052             PEG_METHOD_EXIT();
8053             return false;
8054         }
8055         else if ((creatorValue.getType() != CIMTYPE_STRING) ||
8056                  (creatorValue.isArray()))
8057         {
8058             PEG_TRACE((TRC_INDICATION_SERVICE,Tracer::LEVEL1,
8059                 "Subscription Creator property value of incorrect type:%s %s",
8060                 (creatorValue.isArray()) ? " array of" : " ",
8061                 cimTypeToString(creatorValue.getType())));
8062
8063             //
8064             //  This is a corrupted/invalid instance
8065             //
8066             PEG_METHOD_EXIT();
8067             return false;
8068         }
8069         else
8070         {
8071             creatorValue.get(creator);
8072         }
8073     }
8074     else
8075     {
8076         PEG_TRACE_CSTRING(TRC_INDICATION_SERVICE,Tracer::LEVEL1,
8077             "Missing Subscription Creator property");
8078
8079         //
8080         //  This is a corrupted/invalid instance
8081         //
8082         PEG_METHOD_EXIT();
8083         return false;
8084     }
8085
8086     PEG_METHOD_EXIT();
8087     return true;
8088 }
8089
8090 Boolean IndicationService::_validateState(
8091     const Uint16 state) const
8092 {
8093     //
8094     //  Validate the value
8095     //
8096     if (!Contains(_validStates, state))
8097     {
8098         //
8099         //  This is a corrupted/invalid instance
8100         //
8101         return false;
8102     }
8103
8104     return true;
8105 }
8106
8107 void IndicationService::_updatePropertyList(
8108     CIMName& className,
8109     CIMPropertyList& propertyList,
8110     Boolean& setTimeRemaining,
8111     Boolean& startTimeAdded,
8112     Boolean& durationAdded)
8113 {
8114     PEG_METHOD_ENTER( TRC_INDICATION_SERVICE,
8115         "IndicationService::_updatePropertyList");
8116
8117     //
8118     //  A null propertyList means all properties
8119     //  If the class is Subscription, that includes the Time Remaining property
8120     //
8121     if (className.equal(PEGASUS_CLASSNAME_INDSUBSCRIPTION) ||
8122         className.equal(PEGASUS_CLASSNAME_FORMATTEDINDSUBSCRIPTION))
8123     {
8124         setTimeRemaining = true;
8125     }
8126     else
8127     {
8128         setTimeRemaining = false;
8129     }
8130     startTimeAdded = false;
8131     durationAdded = false;
8132     if (!propertyList.isNull())
8133     {
8134         setTimeRemaining = false;
8135         Array<CIMName> properties = propertyList.getPropertyNameArray();
8136
8137         //
8138         //  Add Creator to property list
8139         //
8140         if (!ContainsCIMName(properties,
8141             PEGASUS_PROPERTYNAME_INDSUB_CREATOR))
8142         {
8143             properties.append(PEGASUS_PROPERTYNAME_INDSUB_CREATOR);
8144         }
8145
8146         if (className.equal(PEGASUS_CLASSNAME_INDHANDLER_CIMXML) ||
8147             className.equal(PEGASUS_CLASSNAME_LSTNRDST_CIMXML))
8148         {
8149             properties.append(PEGASUS_PROPERTYNAME_LSTNRDST_CREATIONTIME);
8150         }
8151
8152         //
8153         //  If a Subscription and Time Remaining is requested,
8154         //  Ensure Subscription Duration and Start Time are in property list
8155         //
8156         if (className.equal(PEGASUS_CLASSNAME_INDSUBSCRIPTION) ||
8157             className.equal(PEGASUS_CLASSNAME_FORMATTEDINDSUBSCRIPTION))
8158         {
8159             if (ContainsCIMName(properties, _PROPERTY_TIMEREMAINING))
8160             {
8161                 setTimeRemaining = true;
8162                 if (!ContainsCIMName(properties, _PROPERTY_STARTTIME))
8163                 {
8164                     properties.append(_PROPERTY_STARTTIME);
8165                     startTimeAdded = true;
8166                 }
8167                 if (!ContainsCIMName(properties, _PROPERTY_DURATION))
8168                 {
8169                     properties.append(_PROPERTY_DURATION);
8170                     durationAdded = true;
8171                 }
8172             }
8173         }
8174         propertyList.clear();
8175         propertyList.set(properties);
8176     }
8177
8178     PEG_METHOD_EXIT();
8179 }
8180
8181 String IndicationService::_getSubscriptionLogString(CIMInstance& subscription)
8182 {
8183     //
8184     //  Get Subscription Filter namespace and Name, and Handler namespace and
8185     //  Name
8186     //
8187     String logString;
8188     CIMValue filterValue;
8189     CIMObjectPath filterPath;
8190     CIMNamespaceName filterNS;
8191     Array<CIMKeyBinding> filterKeyBindings;
8192     CIMValue handlerValue;
8193     CIMObjectPath handlerPath;
8194     CIMNamespaceName handlerNS;
8195     Array<CIMKeyBinding> handlerKeyBindings;
8196     filterValue = subscription.getProperty(subscription.findProperty(
8197         PEGASUS_PROPERTYNAME_FILTER)).getValue();
8198     filterValue.get(filterPath);
8199
8200     //
8201     //  Get Filter namespace - if not set in Filter reference property
8202     //  value, namespace is the namespace of the subscription
8203     //
8204     filterNS = filterPath.getNameSpace();
8205     if (filterNS.isNull())
8206     {
8207         filterNS = subscription.getPath().getNameSpace();
8208     }
8209     logString.append(filterNS.getString());
8210     logString.append(" ");
8211     filterKeyBindings = filterPath.getKeyBindings();
8212     for (Uint32 i = 0; i < filterKeyBindings.size(); i++)
8213     {
8214         if (filterKeyBindings[i].getName().equal(PEGASUS_PROPERTYNAME_NAME))
8215         {
8216             logString.append(filterKeyBindings[i].getValue());
8217             logString.append(", ");
8218             break;
8219         }
8220     }
8221     handlerValue = subscription.getProperty(
8222         subscription.findProperty(PEGASUS_PROPERTYNAME_HANDLER)).getValue();
8223     handlerValue.get(handlerPath);
8224
8225     //
8226     //  Get Handler namespace - if not set in Handler reference property
8227     //  value, namespace is the namespace of the subscription
8228     //
8229     handlerNS = handlerPath.getNameSpace();
8230     if (handlerNS.isNull())
8231     {
8232         handlerNS = subscription.getPath().getNameSpace();
8233     }
8234     logString.append(handlerNS.getString());
8235     logString.append(" ");
8236     handlerKeyBindings = handlerPath.getKeyBindings();
8237     for (Uint32 j = 0; j < handlerKeyBindings.size(); j++)
8238     {
8239         if (handlerKeyBindings[j].getName().equal(PEGASUS_PROPERTYNAME_NAME))
8240         {
8241             logString.append(handlerKeyBindings[j].getValue());
8242             break;
8243         }
8244     }
8245
8246     return logString;
8247 }
8248
8249 String IndicationService::getProviderLogString(CIMInstance& provider)
8250 {
8251     String logString;
8252
8253     logString = provider.getProperty(
8254         provider.findProperty(PEGASUS_PROPERTYNAME_NAME)).getValue().toString();
8255
8256     return logString;
8257 }
8258
8259 CIMClass IndicationService::_getIndicationClass(
8260     const CIMInstance& subscriptionInstance)
8261 {
8262     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
8263     "IndicationService::_getIndicationClass");
8264
8265     CIMNamespaceName sourceNameSpace;
8266     String query;
8267     String queryLanguage;
8268     CIMName indicationClassName;
8269     CIMClass indicationClass;
8270     String filterName;
8271
8272     //  Get filter properties
8273     _subscriptionRepository->getFilterProperties(subscriptionInstance, query,
8274         sourceNameSpace, queryLanguage, filterName);
8275
8276     //  Build the query expression from the filter query
8277     QueryExpression queryExpression = _getQueryExpression(query,
8278                               queryLanguage,
8279                               sourceNameSpace);
8280
8281     //  Get indication class name from filter query
8282     indicationClassName = _getIndicationClassName(
8283     queryExpression, sourceNameSpace);
8284
8285     //
8286     //  Get the indication class object from the repository
8287     //  Specify localOnly=false because superclass properties are needed
8288     //  Specify includeQualifiers=false because qualifiers are not needed
8289     //
8290     indicationClass = _subscriptionRepository->getClass(
8291         sourceNameSpace, indicationClassName, false, false, false,
8292         CIMPropertyList());
8293
8294     PEG_METHOD_EXIT();
8295     return indicationClass;
8296 }
8297
8298 void IndicationService::_getRelevantSubscriptions(
8299     const Array<CIMObjectPath> & providedSubscriptionNames,
8300     const CIMName& className,
8301     const CIMNamespaceName& nameSpace,
8302     const CIMInstance& indicationProvider,
8303     Array<CIMInstance>& subscriptions,
8304     Array<String>& subscriptionKeys)
8305 {
8306     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
8307         "IndicationService::_getRelevantlSubscriptions");
8308
8309     //
8310     // Retrieves list of enabled subscription instances in the specified
8311     // namespace, where the subscription indication class matches or is a
8312     // superclass of the supported class. A subscription is only included
8313     // in the list if the specified provider accepted the subscription.
8314     //
8315     _subscriptionTable->getMatchingClassNamespaceSubscriptions(
8316         className,
8317         nameSpace,
8318         indicationProvider,
8319         subscriptions,
8320         subscriptionKeys);
8321
8322     //
8323     // If the indication provider included subscriptions in the
8324     // SubscriptionInstanceNamesContainer, the subset of subscriptions
8325     // specified by the indication provider that also appear in the initial
8326     // subscriptions list is returned.
8327     //
8328
8329     if (providedSubscriptionNames.size() > 0)
8330     {
8331         for (Uint32 i = 0; i < subscriptions.size(); i++)
8332         {
8333             if (!Contains(providedSubscriptionNames,
8334                           subscriptions[i].getPath()))
8335             {
8336                 subscriptions.remove(i);
8337                 subscriptionKeys.remove(i);
8338                 i--;
8339             }
8340         }
8341     }
8342
8343     PEGASUS_ASSERT(subscriptions.size() == subscriptionKeys.size());
8344     PEG_METHOD_EXIT();
8345 }
8346
8347 Boolean IndicationService::_subscriptionMatch(
8348     const CIMInstance& subscription,
8349     const CIMInstance& indication,
8350     const CIMPropertyList& supportedPropertyList,
8351     QueryExpression& queryExpr,
8352     const CIMNamespaceName sourceNameSpace)
8353 {
8354     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
8355         "IndicationService::_subscriptionMatch");
8356
8357     //
8358     // If supported properties is null (all properties)
8359     // the subscription can be supported
8360     //
8361     if (!supportedPropertyList.isNull ())
8362     {
8363         try
8364         {
8365             // Get the class paths in the FROM list
8366             // Since neither WQL nor CQL support joins, so we can
8367             // assume one class path.
8368             CIMName indicationClassName =
8369                 queryExpr.getClassPathList()[0].getClassName();
8370
8371             if (!_subscriptionRepository->validateIndicationClassName(
8372                 indicationClassName, sourceNameSpace))
8373             {
8374                 //
8375                 // Invalid FROM class, the subscription does not match
8376                 //
8377                 PEG_METHOD_EXIT();
8378                 return false;
8379             }
8380
8381             //
8382             //  Get required property list from filter query (WHERE clause)
8383             //
8384             //  Note:
8385             //  The class should be the class of the indication
8386             //  instance, not the FROM class.
8387             //  This is needed because CQL can have class scoping operators
8388             //  on properties that may not be the same class
8389             //  as the FROM class.  The required properties
8390             //  for an indication are based on indication instance class,
8391             //  not the FROM class.
8392             //
8393
8394             CIMPropertyList requiredPropertyList = _getPropertyList(
8395                 queryExpr, sourceNameSpace, indication.getClassName());
8396
8397             //
8398             //  If the subscription requires all properties,
8399             //  but supported property list does not include all
8400             //  properties, the subscription cannot be supported
8401             //
8402             if (requiredPropertyList.isNull ())
8403             {
8404                 //
8405                 //  Current subscription does not match
8406                 //
8407                 PEG_METHOD_EXIT();
8408                 return false;
8409             }
8410             else
8411             {
8412                 //
8413                 //  Compare subscription required property list
8414                 //  with supported property list
8415                 //
8416                 for (Uint32 j = 0; j < requiredPropertyList.size (); j++)
8417                 {
8418                     if (!ContainsCIMName
8419                         (supportedPropertyList.getPropertyNameArray(),
8420                          requiredPropertyList[j]))
8421                     {
8422                         //
8423                         //  Current subscription does not match
8424                         //
8425                         PEG_METHOD_EXIT();
8426                         return false;
8427                     }
8428                 }
8429             }
8430         }
8431         catch(const Exception & e)
8432         {
8433             // This subscription is invalid
8434            PEG_TRACE ((TRC_DISCARDED_DATA, Tracer::LEVEL1,
8435                 "Exception caught trying to verify required properties "
8436                     "in a subscription are all contained in the list of "
8437                     "supported indication properties: %s",
8438                     (const char *) e.getMessage ().getCString()));
8439             PEG_METHOD_EXIT();
8440             return false;
8441         }
8442         catch(const exception & e)
8443         {
8444             // This subscription is invalid
8445            PEG_TRACE ((TRC_DISCARDED_DATA, Tracer::LEVEL1,
8446                 "Exception caught trying to verify required properties "
8447                     "in a subscription are all contained in the list of "
8448                     "supported indication properties: %s", e.what ()));
8449             PEG_METHOD_EXIT();
8450             return false;
8451         }
8452         catch(...)
8453         {
8454             // This subscription is invalid
8455             // skip it
8456             PEG_TRACE_CSTRING (TRC_DISCARDED_DATA, Tracer::LEVEL1,
8457                 "Unknown exception caught trying to verify "
8458                     "required properties in a subscription are all contained "
8459                     "in the list of supported indication properties.");
8460             PEG_METHOD_EXIT();
8461             return false;
8462         }
8463     }
8464
8465     //
8466     // Check for expired subscription
8467     //
8468     try
8469     {
8470         if (_isExpired(subscription))
8471         {
8472             // Delete expired subscription
8473             CIMObjectPath path = subscription.getPath ();
8474             _deleteExpiredSubscription (path);
8475 #ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
8476             _sendSubscriptionNotActiveMessagetoHandlerService(path);
8477 #endif
8478             PEG_TRACE ((TRC_INDICATION_GENERATION, Tracer::LEVEL3,
8479                 "%s Indication Subscription expired",
8480                 (const char*)(indication.getClassName().getString().
8481                     getCString())));
8482             PEG_METHOD_EXIT();
8483             return false;
8484         }
8485     }
8486     catch (DateTimeOutOfRangeException&)
8487     {
8488         PEG_TRACE_CSTRING(TRC_INDICATION_SERVICE, Tracer::LEVEL2,
8489             "Caught DateTimeOutOfRangeException in IndicationService while"
8490                 "checking for expired subscription");
8491         PEG_METHOD_EXIT();
8492         return false;
8493     }
8494
8495     //
8496     // Evaluate whether the filter criteria are met by the generated
8497     // indication
8498     //
8499     if (!queryExpr.evaluate(indication))
8500     {
8501         PEG_METHOD_EXIT();
8502         return false;
8503     }
8504
8505     PEG_METHOD_EXIT();
8506     return true;
8507 }
8508
8509 Boolean IndicationService::_formatIndication(
8510     CIMInstance& formattedIndication,
8511     QueryExpression& queryExpr,
8512     const Array<CIMName>& providerSupportedProperties,
8513     const Array<CIMName>& indicationClassProperties)
8514 {
8515     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
8516         "IndicationService::_formatIndication");
8517
8518     //
8519     // Call QueryExpression::applyProjection to remove properties
8520     // not listed in the SELECT clause.  Note: for CQL,
8521     // this will handle properties on embedded objects.
8522     //
8523     // QueryExpression::applyProjection throws an exception if
8524     // the indication is missing a required property in the SELECT
8525     // clause.  Although we have checked for the indication missing
8526     // required properties, it would have not detected missing required
8527     // embedded object properties for CQL.  So, we need to catch the
8528     // missing property exception here.
8529     //
8530     try
8531     {
8532         queryExpr.applyProjection(formattedIndication, true);
8533     }
8534     catch (QueryRuntimePropertyException& re)
8535     {
8536         // The indication was missing a required property.
8537         PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL1,
8538             "Apply Projection error: %s",
8539             (const char*)re.getMessage().getCString()));
8540         PEG_METHOD_EXIT();
8541         return false;
8542     }
8543
8544     //
8545     // Remove any properties that may be left on the indication
8546     // that are not in the indication class.  These are properties
8547     // added by the provider incorrectly.  It is possible that
8548     // these properties will remain after applyProjection if the
8549     // SELECT clause happens to have a property name not on the
8550     // indication class, and the indication has that same property.
8551     // Note: If SELECT includes all properties ("*"), it's still
8552     // necessary to check, in case the provider added properties
8553     // not in the indication class.
8554     //
8555     for (Uint32 j = 0; j < providerSupportedProperties.size(); j++)
8556     {
8557         Uint32 rmIndex =
8558             formattedIndication.findProperty(providerSupportedProperties[j]);
8559         if (rmIndex != PEG_NOT_FOUND &&
8560             !ContainsCIMName(
8561                  indicationClassProperties, providerSupportedProperties[j]))
8562         {
8563             formattedIndication.removeProperty(rmIndex);
8564         }
8565     }
8566
8567     PEG_METHOD_EXIT();
8568     return true;
8569 }
8570
8571 void IndicationService::_forwardIndToHandler(
8572     const CIMInstance& matchedSubscription,
8573     const CIMInstance& handlerInstance,
8574     const CIMInstance& formattedIndication,
8575     const CIMNamespaceName& namespaceName,
8576     const OperationContext& operationContext)
8577 {
8578     PEG_METHOD_ENTER(TRC_INDICATION_SERVICE,
8579         "IndicationService::_forwardIndToHandler");
8580
8581     CIMRequestMessage * handler_request =
8582         new CIMHandleIndicationRequestMessage (
8583             XmlWriter::getNextMessageId (),
8584             namespaceName,
8585             handlerInstance,
8586             formattedIndication,
8587             matchedSubscription,
8588             QueueIdStack(_handlerService, getQueueId()),
8589             String::EMPTY,
8590             String::EMPTY);
8591
8592     handler_request->operationContext = operationContext;
8593
8594     AsyncLegacyOperationStart *async_req =
8595         new AsyncLegacyOperationStart(
8596         0,
8597         _handlerService,
8598         handler_request);
8599
8600     PEG_TRACE((TRC_INDICATION_SERVICE, Tracer::LEVEL4,
8601         "Sending (SendAsync) Indication to %s "
8602         "via CIMHandleIndicationRequestMessage",
8603         (MessageQueue::lookup(_handlerService) ?
8604          MessageQueue::lookup(_handlerService)->getQueueName() :
8605         "BAD queue name")));
8606
8607     SendForget(async_req);
8608
8609     PEG_METHOD_EXIT();
8610 }
8611
8612 PEGASUS_NAMESPACE_END