1 xinf.zhao 1.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 xinf.zhao 1.1 // 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 #include "CQLOperationRequestDispatcher.h"
32
33 #include <Pegasus/Common/AutoPtr.h>
34 #include <Pegasus/Common/QueryExpressionRep.h>
35 #include <Pegasus/Common/StatisticalData.h>
36 #include <Pegasus/Provider/CIMOMHandleQueryContext.h>
37
38 PEGASUS_NAMESPACE_BEGIN
39
40 PEGASUS_USING_STD;
41
42 void CQLOperationRequestDispatcher::applyQueryToEnumeration(
43 xinf.zhao 1.1 CIMResponseMessage* msg,
44 QueryExpressionRep* query)
45 {
46 PEG_METHOD_ENTER(TRC_DISPATCHER,
47 "CQLOperationRequestDispatcher::applyQueryToEnumeration");
48
49 CIMEnumerateInstancesResponseMessage* enr =
50 (CIMEnumerateInstancesResponseMessage*) msg;
51 CQLSelectStatement* qs = ((CQLQueryExpressionRep*)query)->_stmt;
52
53 Array<CIMInstance>& a = enr->getResponseData().getInstances();
54
55 for (int i = a.size() - 1; i >= 0; i--)
56 {
57
58 try
59 {
60 if (qs->evaluate(a[i]))
61 {
62 //
63 // Specify that missing requested project properties are
64 xinf.zhao 1.1 // allowed to be consistent with clarification from DMTF
65 qs->applyProjection(a[i], true);
66 }
67 else
68 {
69 a.remove(i);
70 }
71 }
72 catch (...)
73 {
74 a.remove(i);
75 }
76 }
77 PEG_METHOD_EXIT();
78 }
79
80 void CQLOperationRequestDispatcher::handleQueryResponseAggregation(
81 OperationAggregate* poA)
82 {
83 PEG_METHOD_ENTER(TRC_DISPATCHER,
84 "CQLOperationRequestDispatcher::handleQueryResponseAggregation");
85 xinf.zhao 1.1 Uint32 numberResponses = poA->numberResponses();
86
87 if (numberResponses == 0)
88 return;
89
90 CIMResponseMessage* response = poA->getResponse(0);
91 CIMExecQueryResponseMessage* toResponse = 0;
92 Uint32 startIndex = 0;
93 Uint32 endIndex = numberResponses - 1;
94 Boolean manyResponses = true;
95 if (response->getType() == CIM_ENUMERATE_INSTANCES_RESPONSE_MESSAGE)
96 {
97 // Create an ExecQuery response from an EnumerateInstances request
98 CIMRequestMessage* request = poA->getRequest();
99 AutoPtr<CIMExecQueryResponseMessage> query(
100 new CIMExecQueryResponseMessage(
101 request->messageId,
102 CIMException(),
103 request->queueIds.copyAndPop()));
104 query->syncAttributes(request);
105 toResponse = query.release();
106 xinf.zhao 1.1 }
107 else
108 {
109 toResponse = (CIMExecQueryResponseMessage*) response;
110 manyResponses = false;
111 }
112
113 // Work backward and delete each response off the end of the array
114 for (Uint32 i = endIndex; i >= startIndex; i--)
115 {
116 if (manyResponses)
117 {
118 response = poA->getResponse(i);
119 }
120 if (response->getType() == CIM_ENUMERATE_INSTANCES_RESPONSE_MESSAGE)
121 {
122 // convert enumerate instances responses to exec query responses
123 applyQueryToEnumeration(response, poA->_query);
124 CIMEnumerateInstancesResponseMessage* fromResponse =
125 (CIMEnumerateInstancesResponseMessage*) response;
126 CIMClass cimClass;
127 xinf.zhao 1.1
128 Boolean clsRead=false;
129 Array<CIMInstance>& a =
130 fromResponse->getResponseData().getInstances();
131 for (Uint32 j = 0, m = a.size();
132 j < m; j++)
133 {
134 CIMObject co=CIMObject(a[j]);
135 CIMObjectPath op=co.getPath();
136 const Array<CIMKeyBinding>& kbs=op.getKeyBindings();
137 if (kbs.size() == 0)
138 { // no path set why ?
139 if (clsRead == false)
140 {
141 cimClass = _repository->getClass(
142 poA->_nameSpace, op.getClassName(),
143 false,true,false, CIMPropertyList());
144 clsRead=true;
145 }
146 op = a[j].buildPath(cimClass);
147 }
148 xinf.zhao 1.1 op.setNameSpace(poA->_nameSpace);
149 op.setHost(System::getHostName());
150 co.setPath(op);
151 if (manyResponses)
152 toResponse->getResponseData().appendObject(co);
153 }
154 }
155 else
156 {
157 CIMExecQueryResponseMessage* fromResponse =
158 (CIMExecQueryResponseMessage*) response;
159
160 CIMResponseData & from = fromResponse->getResponseData();
161 from.completeHostNameAndNamespace(
162 System::getHostName(),
163 poA->_nameSpace);
164
165 if (manyResponses)
166 {
167 toResponse->getResponseData().appendResponseData(from);
168 }
169 xinf.zhao 1.1 }
170 if (manyResponses)
171 {
172 poA->deleteResponse(i);
173 }
174
175 if (i == 0)
176 break;
177 } // for all responses in response list
178
179 // if we started with an enumerateInstances repsonse, then add it to overall
180 if ((startIndex == 0) && manyResponses)
181 {
182 poA->appendResponse(toResponse);
183 }
184
185 PEG_METHOD_EXIT();
186 }
187
188 void CQLOperationRequestDispatcher::handleQueryRequest(
189 CIMExecQueryRequestMessage* request)
190 xinf.zhao 1.1 {
191 PEG_METHOD_ENTER(TRC_DISPATCHER,
192 "CQLOperationRequestDispatcher::handleQueryRequest");
193 Boolean exception=false;
194
195 CIMOMHandle _ch;
196 CIMOMHandleQueryContext _queryOrig(request->nameSpace,_ch);
197
198 AutoPtr<CQLSelectStatement> selectStatement(
199 new CQLSelectStatement(request->queryLanguage,
200 request->query,
201 _queryOrig));
202
203 AutoPtr<CQLQueryExpressionRep> qx;
204 CIMException cimException;
205 CIMName className;
206
207 if (request->queryLanguage != "DMTF:CQL")
208 {
209 cimException = PEGASUS_CIM_EXCEPTION(
210 CIM_ERR_QUERY_LANGUAGE_NOT_SUPPORTED, request->queryLanguage);
211 xinf.zhao 1.1 exception=true;
212 }
213 else
214 {
215 try
216 {
217 CQLParser::parse(request->query, *selectStatement.get());
218
219 Array<CIMObjectPath> classPath =
220 selectStatement->getClassPathList();
221 className = classPath[0].getClassName();
222 qx.reset(
223 new CQLQueryExpressionRep("DMTF:CQL", selectStatement.get()));
224 selectStatement.release();
225 }
226 catch (ParseError&)
227 {
228 cimException =
229 PEGASUS_CIM_EXCEPTION(CIM_ERR_INVALID_QUERY, request->query);
230 exception=true;
231 }
232 xinf.zhao 1.1 catch (MissingNullTerminator&)
233 {
234 cimException =
235 PEGASUS_CIM_EXCEPTION(CIM_ERR_INVALID_QUERY, request->query);
236 exception = true;
237 }
238
239 if (exception == false)
240 {
241 if (!_checkExistenceOfClass(request->nameSpace, className))
242 {
243 cimException = PEGASUS_CIM_EXCEPTION(
244 CIM_ERR_INVALID_CLASS, className.getString());
245 exception = true;
246 }
247 }
248 }
249
250 if (exception)
251 {
252 CIMResponseMessage* response = request->buildResponse();
253 xinf.zhao 1.1 response->cimException = cimException;
254
255 _enqueueResponse(request, response);
256 PEG_METHOD_EXIT();
257 return;
258 }
259
260 // Get names of descendent classes:
261 Array<ProviderInfo> providerInfos;
262
263 // This gets set by _lookupAllInstanceProviders()
264 Uint32 providerCount;
265
266 try
267 {
268 providerInfos =
269 _lookupAllInstanceProviders(
270 request->nameSpace,
271 className,
272 providerCount);
273 }
274 xinf.zhao 1.1 catch (CIMException& e)
275 {
276 // Return exception response if exception from getSubClasses
277 CIMResponseMessage* response = request->buildResponse();
278 response->cimException = e;
279
280 _enqueueResponse(request, response);
281 PEG_METHOD_EXIT();
282 return;
283 }
284
285 // Test for "enumerate too Broad" and if so, execute exception.
286 // This limits the number of provider invocations, not the number
287 // of instances returned.
288 if (providerCount > _maximumEnumerateBreadth)
289 {
290 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL1,
291 "ERROR: Enumerate operation too broad for class %s. "
292 "Limit = %u, providerCount = %u",
293 (const char*)request->className.getString().getCString(),
294 _maximumEnumerateBreadth,
295 xinf.zhao 1.1 providerCount));
296
297 CIMResponseMessage* response = request->buildResponse();
298 response->cimException =
299 PEGASUS_CIM_EXCEPTION_L(CIM_ERR_NOT_SUPPORTED, MessageLoaderParms(
300 "Server.CQLOperationRequestDispatcher.QUERY_REQ_TOO_BROAD",
301 "The query request is too broad."));
302
303 _enqueueResponse(request, response);
304 PEG_METHOD_EXIT();
305 return;
306 }
307
308 // If no provider is registered and the repository isn't the default,
309 // return CIM_ERR_NOT_SUPPORTED
310 if ((providerCount == 0) && !(_repository->isDefaultInstanceProvider()))
311 {
312 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL2,
313 "CIM_ERROR_NOT_SUPPORTED for %s",
314 (const char*)request->className.getString().getCString()));
315
316 xinf.zhao 1.1 CIMResponseMessage* response = request->buildResponse();
317 response->cimException =
318 PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, String::EMPTY);
319
320 _enqueueResponse(request, response);
321 PEG_METHOD_EXIT();
322 return;
323 }
324
325 // We have instances for Providers and possibly repository.
326 // Set up an aggregate object and save a copy of the original request.
327
328 OperationAggregate* poA= new OperationAggregate(
329 new CIMExecQueryRequestMessage(*request),
330 request->getType(),
331 request->messageId,
332 request->queueIds.top(),
333 className, CIMNamespaceName(),
334 qx.release(),
335 "DMTF:CQL");
336
337 xinf.zhao 1.1 // Set the number of expected responses in the OperationAggregate
338 Uint32 numClasses = providerInfos.size();
339 poA->_aggregationSN = cimOperationAggregationSN++;
340 poA->_nameSpace=request->nameSpace;
341 if (_repository->isDefaultInstanceProvider())
342 {
343 // Loop through providerInfos, forwarding requests to repository
344 for (Uint32 i = 0; i < numClasses; i++)
345 {
346 ProviderInfo& providerInfo = providerInfos[i];
347
348 // this class is registered to a provider - skip
349 if (providerInfo.hasProvider)
350 continue;
351
352 // If this class does not have a provider
353
354 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL4,
355 "Routing ExecQuery request for class %s to the "
356 "repository. Class # %u of %u, aggregation SN %u.",
357 (const char*)providerInfo.className.getString().getCString(),
358 xinf.zhao 1.1 (unsigned int)(i + 1),
359 (unsigned int)(numClasses),
360 (unsigned int)(poA->_aggregationSN)));
361
362 // Create an EnumerateInstances response from an ExecQuery request
363 AutoPtr<CIMEnumerateInstancesResponseMessage> response(
364 new CIMEnumerateInstancesResponseMessage(
365 request->messageId,
366 CIMException(),
367 request->queueIds.copyAndPop()));
368 response->syncAttributes(request);
369
370 try
371 {
372 // Enumerate instances only for this class
373 response->getResponseData().setInstances(
374 _repository->enumerateInstancesForClass(
375 request->nameSpace,
376 providerInfo.className));
377 }
378 catch (CIMException& e)
379 xinf.zhao 1.1 {
380 response->cimException = e;
381 }
382 catch (Exception& e)
383 {
384 response->cimException = PEGASUS_CIM_EXCEPTION(
385 CIM_ERR_FAILED, e.getMessage());
386 }
387 catch (...)
388 {
389 response->cimException = PEGASUS_CIM_EXCEPTION(
390 CIM_ERR_FAILED, String::EMPTY);
391 }
392
393 poA->appendResponse(response.release());
394 } // for all classes and derived classes
395
396 Uint32 numberResponses = poA->numberResponses();
397 Uint32 totalIssued = providerCount + (numberResponses > 0 ? 1 : 0);
398 poA->setTotalIssued(totalIssued);
399
400 xinf.zhao 1.1 if (numberResponses > 0)
401 {
402 handleEnumerateInstancesResponseAggregation(poA,false);
403 CIMResponseMessage* response = poA->removeResponse(0);
404 _forwardRequestForAggregation(
405 getQueueId(),
406 String(),
407 new CIMExecQueryRequestMessage(*request),
408 poA, response);
409 }
410 } // if isDefaultInstanceProvider
411 else
412 {
413 // Set the number of expected responses in the OperationAggregate
414 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL4,
415 "providerCount:%u",(unsigned int)providerCount));
416 poA->setTotalIssued(providerCount);
417 }
418
419 // Loop through providerInfos, forwarding requests to providers
420 for (Uint32 i = 0; i < numClasses; i++)
421 xinf.zhao 1.1 {
422 // If this class has a provider
423 ProviderInfo& providerInfo = providerInfos[i];
424
425 // this class is NOT registered to a provider - skip
426 if (!providerInfo.hasProvider)
427 continue;
428 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL4,
429 "Routing ExecQuery request for class %s to "
430 "service \"%s\" for control provider \"%s\". "
431 "Class # %u of %u, aggregation SN %u.",
432 (const char*)providerInfo.className.getString().getCString(),
433 lookup(providerInfo.serviceId)->getQueueName(),
434 (const char*)providerInfo.controlProviderName.getCString(),
435 (unsigned int)(i + 1),
436 (unsigned int)numClasses,
437 (unsigned int)(poA->_aggregationSN)));
438
439 ProviderIdContainer* providerIdContainer =
440 providerInfo.providerIdContainer.get();
441
442 xinf.zhao 1.1 if (providerInfo.hasNoQuery)
443 {
444 OperationContext* context = &request->operationContext;
445 const OperationContext::Container* container = 0;
446 container = &context->get(IdentityContainer::NAME);
447 const IdentityContainer& identityContainer =
448 dynamic_cast<const IdentityContainer&>(*container);
449
450 AutoPtr<CIMEnumerateInstancesRequestMessage> enumReq(
451 new CIMEnumerateInstancesRequestMessage(
452 request->messageId,
453 request->nameSpace,
454 providerInfo.className,
455 false,false,false,
456 CIMPropertyList(),
457 request->queueIds,
458 request->authType,
459 identityContainer.getUserName()));
460
461 context = &enumReq->operationContext;
462 if (providerIdContainer)
463 xinf.zhao 1.1 context->insert(*providerIdContainer);
464 context->insert(identityContainer);
465 _forwardRequestForAggregation(
466 providerInfo.serviceId,
467 providerInfo.controlProviderName,
468 enumReq.release(), poA);
469 }
470 else
471 {
472 AutoPtr<CIMExecQueryRequestMessage> requestCopy(
473 new CIMExecQueryRequestMessage(*request));
474
475 OperationContext* context = &request->operationContext;
476 if (providerIdContainer)
477 context->insert(*providerIdContainer);
478
479 requestCopy->operationContext = *context;
480 requestCopy->className = providerInfo.className;
481
482 _forwardRequestForAggregation(
483 providerInfo.serviceId,
484 xinf.zhao 1.1 providerInfo.controlProviderName,
485 requestCopy.release(), poA);
486 }
487 } // for all classes and derived classes
488
489
490 PEG_METHOD_EXIT();
491 }
492
493 PEGASUS_NAMESPACE_END
|