1 /*****************************************************************************/
2 /* Software Testing Automation Framework (STAF)                              */
3 /* (C) Copyright IBM Corp. 2001, 2004, 2005                                  */
4 /*                                                                           */
5 /* This software is licensed under the Eclipse Public License (EPL) V1.0.    */
6 /*****************************************************************************/
7 
8 #include "STAF.h"
9 #include "STAFProc.h"
10 #include "STAFProcUtil.h"
11 #include "STAFQueueService.h"
12 #include "STAFHandleQueue.h"
13 #include "STAFHandleManager.h"
14 #include "STAFVariablePool.h"
15 #include "STAFUtil.h"
16 // XXX: Remove STAFServiceManager.h if pass in default authenticator via
17 //      LocalRequest()
18 #include "STAFServiceManager.h"
19 
20 static const STAFString sColon(kUTF8_COLON);
21 static STAFString sHelpMsg;
22 
STAFQueueService()23 STAFQueueService::STAFQueueService() : STAFService("QUEUE")
24 {
25     // Assign the help text string for the service
26 
27     sHelpMsg = STAFString("*** QUEUE Service Help ***") +
28         *gLineSeparatorPtr + *gLineSeparatorPtr +
29         "QUEUE  MESSAGE <Message>" +
30         *gLineSeparatorPtr +
31         "       [HANDLE <Handle>] | [NAME <Name>] [PRIORITY <Priority>] [TYPE <Type>]" +
32         *gLineSeparatorPtr + *gLineSeparatorPtr +
33         "GET    [PRIORITY <Priority>]... [MACHINE <Endpoint>]... [NAME <Name>]..." +
34         *gLineSeparatorPtr +
35         "       [HANDLE <Handle>]... [USER <User>]... [TYPE <Type>]..." +
36         *gLineSeparatorPtr +
37         "       [CONTAINS <String>]... [ICONTAINS <String>]... " +
38         *gLineSeparatorPtr +
39         "       [FIRST <Number> | ALL]" +
40         *gLineSeparatorPtr +
41         "       [WAIT [<Number>[s|m|h|d|w]]]" +
42         *gLineSeparatorPtr + *gLineSeparatorPtr +
43         "PEEK   [PRIORITY <Priority>]... [MACHINE <Endpoint>]... [NAME <Name>]..." +
44         *gLineSeparatorPtr +
45         "       [HANDLE <Handle>]... [USER <User>]... [TYPE <Type>]..." +
46         *gLineSeparatorPtr +
47         "       [CONTAINS <String>]... [ICONTAINS <String>]... " +
48         *gLineSeparatorPtr +
49         "       [FIRST <Number> | ALL]" +
50         *gLineSeparatorPtr +
51         "       [WAIT [<Number>[s|m|h|d|w]]]" +
52         *gLineSeparatorPtr + *gLineSeparatorPtr +
53         "DELETE [PRIORITY <Priority>]... [MACHINE <Endpoint>]... [NAME <Name>]..." +
54         *gLineSeparatorPtr +
55         "       [HANDLE <Handle>]... [USER <User>]... [TYPE <Type>]..." +
56         *gLineSeparatorPtr +
57         "       [CONTAINS <String>]... [ICONTAINS <String>]... " +
58         *gLineSeparatorPtr + *gLineSeparatorPtr +
59         "LIST   [HANDLE <Handle>]" +
60         *gLineSeparatorPtr + *gLineSeparatorPtr +
61         "HELP";
62 
63     // Create the command request parsers
64 
65     // queue options
66 
67     fQueueParser.addOption("QUEUE",    1,
68         STAFCommandParser::kValueNotAllowed);
69     fQueueParser.addOption("HANDLE",   1,
70         STAFCommandParser::kValueRequired);
71     fQueueParser.addOption("NAME",     1,
72         STAFCommandParser::kValueRequired);
73     fQueueParser.addOption("PRIORITY", 1,
74         STAFCommandParser::kValueRequired);
75     fQueueParser.addOption("MESSAGE",  1,
76         STAFCommandParser::kValueRequired);
77     fQueueParser.addOption("TYPE",  1,
78         STAFCommandParser::kValueRequired);
79 
80     // queue option groups
81 
82     fQueueParser.addOptionGroup("HANDLE NAME", 0, 1);
83     fQueueParser.addOptionGroup("MESSAGE",     1, 1);
84 
85     // get / peek options
86 
87     fGetParser.addOption("GET",       1,
88         STAFCommandParser::kValueNotAllowed);
89     fGetParser.addOption("PEEK",      1,
90         STAFCommandParser::kValueNotAllowed);
91     fGetParser.addOption("PRIORITY",  0,
92         STAFCommandParser::kValueRequired);
93     fGetParser.addOption("MACHINE",   0,
94         STAFCommandParser::kValueRequired);
95     fGetParser.addOption("NAME",      0,
96         STAFCommandParser::kValueRequired);
97     fGetParser.addOption("HANDLE",    0,
98         STAFCommandParser::kValueRequired);
99     fGetParser.addOption("USER",      0,
100         STAFCommandParser::kValueRequired);
101     fGetParser.addOption("TYPE",      0,
102         STAFCommandParser::kValueRequired);
103     fGetParser.addOption("CONTAINS",  0,
104         STAFCommandParser::kValueRequired);
105     fGetParser.addOption("ICONTAINS", 0,
106         STAFCommandParser::kValueRequired);
107     fGetParser.addOption("WAIT",      1,
108         STAFCommandParser::kValueAllowed);
109     fGetParser.addOption("FIRST",      1,
110         STAFCommandParser::kValueRequired);
111     fGetParser.addOption("ALL",      1,
112         STAFCommandParser::kValueNotAllowed);
113 
114     fGetParser.addOptionGroup("FIRST ALL", 0, 1);
115 
116     // delete options
117 
118     fDeleteParser.addOption("DELETE",    1,
119         STAFCommandParser::kValueNotAllowed);
120     fDeleteParser.addOption("PRIORITY",  0,
121         STAFCommandParser::kValueRequired);
122     fDeleteParser.addOption("MACHINE",   0,
123         STAFCommandParser::kValueRequired);
124     fDeleteParser.addOption("NAME",      0,
125         STAFCommandParser::kValueRequired);
126     fDeleteParser.addOption("HANDLE",    0,
127         STAFCommandParser::kValueRequired);
128     fDeleteParser.addOption("USER",      0,
129         STAFCommandParser::kValueRequired);
130     fDeleteParser.addOption("TYPE",      0,
131         STAFCommandParser::kValueRequired);
132     fDeleteParser.addOption("CONTAINS",  0,
133         STAFCommandParser::kValueRequired);
134     fDeleteParser.addOption("ICONTAINS", 0,
135         STAFCommandParser::kValueRequired);
136 
137     // list options
138 
139     fListParser.addOption("LIST",   1,
140         STAFCommandParser::kValueNotAllowed);
141     fListParser.addOption("HANDLE", 1,
142         STAFCommandParser::kValueRequired);
143 
144     // Construct map class for an entry in a queue
145 
146     fQueueEntryMapClass = STAFMapClassDefinition::create(
147         "STAF/Service/Queue/Entry");
148 
149     fQueueEntryMapClass->addKey("priority",   "Priority");
150     fQueueEntryMapClass->setKeyProperty("priority", "display-short-name", "P");
151     fQueueEntryMapClass->addKey("timestamp",  "Date-Time");
152     fQueueEntryMapClass->addKey("machine",    "Machine");
153     fQueueEntryMapClass->addKey("handleName", "Handle Name");
154     fQueueEntryMapClass->setKeyProperty(
155         "handleName", "display-short-name", "Name");
156     fQueueEntryMapClass->addKey("handle",     "Handle");
157     fQueueEntryMapClass->setKeyProperty("handle", "display-short-name", "H#");
158     fQueueEntryMapClass->addKey("user",       "User");
159     fQueueEntryMapClass->addKey("type",       "Type");
160     fQueueEntryMapClass->addKey("message",    "Message");
161 
162     // Construct map classes for handles with a full queue error
163 
164     fQueueFullMapClass = STAFMapClassDefinition::create(
165         "STAF/Service/Queue/FullInfo");
166     fQueueFullMapClass->addKey("handle", "Handle");
167     fQueueFullMapClass->addKey("queueSize", "Queue Size");
168 
169     fQueueErrorMapClass = STAFMapClassDefinition::create(
170         "STAF/Service/Queue/Error");
171     fQueueErrorMapClass->addKey("numberQueued", "Number Queued");
172     fQueueErrorMapClass->addKey("fullQueueList", "Handles with Full Queues");
173 }
174 
175 
~STAFQueueService()176 STAFQueueService::~STAFQueueService()
177 {
178     /* Do Nothing */
179 }
180 
181 
info(unsigned int) const182 STAFString STAFQueueService::info(unsigned int) const
183 {
184     return name() + ": Internal";
185 }
186 
187 
acceptRequest(const STAFServiceRequest & requestInfo)188 STAFServiceResult STAFQueueService::acceptRequest(
189     const STAFServiceRequest &requestInfo)
190 {
191     STAFString action = requestInfo.fRequest.subWord(0, 1).lowerCase();
192 
193     if      (action == "queue")  return handleQueue(requestInfo);
194     else if (action == "get")    return handleGetPeek(requestInfo, true);
195     else if (action == "peek")   return handleGetPeek(requestInfo, false);
196     else if (action == "delete") return handleDelete(requestInfo);
197     else if (action == "list")   return handleList(requestInfo);
198     else if (action == "help")   return handleHelp(requestInfo);
199     else
200     {
201         STAFString errMsg = STAFString("'") +
202             requestInfo.fRequest.subWord(0, 1) +
203             "' is not a valid command request for the " + name() +
204             " service" + *gLineSeparatorPtr + *gLineSeparatorPtr +
205             sHelpMsg;
206 
207         return STAFServiceResult(kSTAFInvalidRequestString, errMsg);
208     }
209 }
210 
211 
handleQueue(const STAFServiceRequest & requestInfo)212 STAFServiceResult STAFQueueService::handleQueue(
213     const STAFServiceRequest &requestInfo)
214 {
215     // Verify that the requesting machine/user has at least trust level 3
216 
217     IVALIDATE_TRUST(3, "QUEUE");
218 
219     // Parse the request
220 
221     STAFCommandParseResultPtr parsedResult = fQueueParser.parse(
222         requestInfo.fRequest);
223 
224     if (parsedResult->rc != kSTAFOk)
225     {
226         return STAFServiceResult(kSTAFInvalidRequestString,
227                                  parsedResult->errorBuffer, 0);
228     }
229 
230     STAFString errorBuffer;
231 
232     // HANDLE may only default if the request came from this machine
233 
234     if ((parsedResult->optionTimes("HANDLE") == 0) &&
235         (parsedResult->optionTimes("NAME") == 0) &&
236         !requestInfo.fIsLocalRequest)
237     {
238         return STAFServiceResult(kSTAFInvalidRequestString);
239     }
240 
241     DEFINE_VAR_POOL_LIST(varPoolList, varPoolListSize, requestInfo);
242     STAFString name;
243     STAFHandle_t theHandle = requestInfo.fHandle;
244     unsigned int priority = 5;
245     STAFString type;
246 
247     STAFRC_t rc = RESOLVE_OPTIONAL_STRING_OPTION("NAME", name);
248 
249     if (!rc) rc = RESOLVE_OPTIONAL_UINT_OPTION_RANGE(
250         "HANDLE", theHandle, gHandleManagerPtr->getMinHandleNumber(),
251         gHandleManagerPtr->getMaxHandleNumber());
252 
253     if (!rc) rc = RESOLVE_OPTIONAL_UINT_OPTION("PRIORITY", priority);
254     if (!rc) rc = RESOLVE_OPTIONAL_STRING_OPTION("TYPE", type);
255 
256     if (rc) return STAFServiceResult(rc, errorBuffer);
257 
258     // Currently we won't resolve variables in MESSAGE
259 
260     STAFHandleQueuePtr handleQueue;
261     STAFString machine = requestInfo.fEndpoint;
262 
263     STAFString result;
264 
265     STAFHandleQueue::Message message(priority, machine,
266                                      requestInfo.fAuthenticator,
267                                      requestInfo.fUserIdentifier,
268                                      requestInfo.fHandleName,
269                                      requestInfo.fHandle,
270                                      parsedResult->optionValue("MESSAGE"),
271                                      type);
272 
273     if (parsedResult->optionTimes("NAME") == 0)
274     {
275         rc = gHandleManagerPtr->handleQueue(theHandle, handleQueue);
276 
277         if (rc) return STAFServiceResult(rc);
278 
279         STAFMutexSemLock queueLock(handleQueue->fQueueSem);
280 
281         if (handleQueue->fQueue.size() >= gMaxQueueSize)
282         {
283             return STAFServiceResult(kSTAFQueueFull,
284                                      STAFString(handleQueue->fQueue.size()));
285         }
286 
287         handleQueue->fQueue.insert(STAFHandleQueue::HandleQueue::value_type(
288             message.priority, message));
289         handleQueue->fNotify->post();
290     }
291     else
292     {
293         std::vector<STAFHandle_t> handles =
294                                   gHandleManagerPtr->handlesWithName(name);
295 
296         std::vector<STAFHandle_t>::iterator iter;
297 
298         unsigned int numberQueued = handles.size();
299 
300         STAFObjectPtr fullQueueErrorList = STAFObject::createList();
301 
302         for (iter = handles.begin(); iter != handles.end(); iter++)
303         {
304             if (gHandleManagerPtr->handleQueue(*iter, handleQueue))
305                 --numberQueued;
306             else
307             {
308                 STAFMutexSemLock queueLock(handleQueue->fQueueSem);
309 
310                 if (handleQueue->fQueue.size() >= gMaxQueueSize)
311                 {
312                     --numberQueued;
313 
314                     // Add information about the handle's full queue to the
315                     // error list
316 
317                     STAFObjectPtr errorMap = fQueueFullMapClass->createInstance();
318                     errorMap->put("handle", STAFString(*iter));
319                     errorMap->put("queueSize", handleQueue->fQueue.size());
320                     fullQueueErrorList->append(errorMap);
321                 }
322                 else
323                 {
324                     handleQueue->fQueue.insert(
325                     STAFHandleQueue::HandleQueue::value_type(
326                         message.priority, message));
327                     handleQueue->fNotify->post();
328                 }
329             }
330         }
331 
332         if (fullQueueErrorList->size() > 0)
333         {
334             // At least one message was not successfully queued
335 
336             // Create a marshalled map containing error information including
337             // the number of handles that the message was successfully queued
338             // to and a list of the handles where the message could not be
339             // queued because the queues were full
340 
341             STAFObjectPtr mc = STAFObject::createMarshallingContext();
342             mc->setMapClassDefinition(fQueueErrorMapClass->reference());
343             mc->setMapClassDefinition(fQueueFullMapClass->reference());
344             STAFObjectPtr errorMap = fQueueErrorMapClass->createInstance();
345             errorMap->put("numberQueued", STAFString(numberQueued));
346             errorMap->put("fullQueueList", fullQueueErrorList);
347 
348             mc->setRootObject(errorMap);
349 
350             return STAFServiceResult(kSTAFQueueFull, mc->marshall());
351         }
352         else if (numberQueued == 0)
353         {
354             // No handles exist with the specified handle name
355 
356             return STAFServiceResult(kSTAFHandleDoesNotExist);
357         }
358 
359         result = STAFString(numberQueued);
360     }
361 
362     return STAFServiceResult(kSTAFOk, result);
363 }
364 
365 
handleGetPeek(const STAFServiceRequest & requestInfo,bool isGet)366 STAFServiceResult STAFQueueService::handleGetPeek(
367     const STAFServiceRequest &requestInfo, bool isGet)
368 {
369     // Verify that this request came from the local machine
370     // No check of trust is needed since these commands are only valid
371     // with respect to the submitting process' queue so just set
372     // required trust level to 0.
373 
374     if (isGet)
375     {
376         IVALIDATE_LOCAL_TRUST(0, "GET");
377     }
378     else
379     {
380         IVALIDATE_LOCAL_TRUST(0, "PEEK");
381     }
382 
383     // Parse the request
384 
385     STAFCommandParseResultPtr parsedResult = fGetParser.parse(
386         requestInfo.fRequest);
387 
388     if (parsedResult->rc != kSTAFOk)
389     {
390         return STAFServiceResult(kSTAFInvalidRequestString,
391                                  parsedResult->errorBuffer, 0);
392     }
393 
394     DEFINE_VAR_POOL_LIST(varPoolList, varPoolListSize, requestInfo);
395     STAFString errorBuffer;
396     STAFHandleQueuePtr handleQueue;
397     STAFRC_t rc = gHandleManagerPtr->handleQueue(requestInfo.fHandle,
398                                                  handleQueue);
399     if (rc) return STAFServiceResult(rc);
400 
401     // Check if the ALL or FIRST option was specified
402 
403     bool first = false;  // Indicates if the FIRST option is specified
404     bool all = false;    // Indicates if the ALL option is specified
405     unsigned int firstNum = 0;  // Number of queue entries to obtain
406 
407     if (parsedResult->optionTimes("ALL") > 0)
408     {
409         all = true;
410     }
411     else if (parsedResult->optionTimes("FIRST") > 0)
412     {
413         rc = RESOLVE_UINT_OPTION_RANGE("FIRST", firstNum, 1, UINT_MAX);
414 
415         if (rc) return STAFServiceResult(rc, errorBuffer);
416 
417         first = true;
418     }
419     else
420     {
421         // Default to FIRST 1 if neither the ALL or FIRST option is
422         // specified
423 
424         firstNum = 1;
425     }
426 
427     std::vector<unsigned int> priorityList;
428     std::vector<unsigned int> handleList;
429     std::vector<STAFString> machineList;
430     std::vector<STAFString> nameList;
431     std::vector<STAFString> userList;
432     std::vector<STAFString> typeList;
433     std::vector<STAFString> containsList;
434     std::vector<STAFString> icontainsList;
435 
436     unsigned int index = 0;
437     unsigned int optionCount = 0;
438     unsigned int priority = 0;
439 
440     for (index = 1, optionCount = parsedResult->optionTimes("PRIORITY");
441          (index <= optionCount) && !rc; ++index)
442     {
443         rc = RESOLVE_INDEXED_UINT_OPTION("PRIORITY", index, priority);
444         if (!rc) priorityList.push_back(priority);
445     }
446 
447     STAFHandle_t theHandle = 0;
448 
449     for (index = 1, optionCount = parsedResult->optionTimes("HANDLE");
450          (index <= optionCount) && !rc; ++index)
451     {
452         rc = RESOLVE_INDEXED_UINT_OPTION_RANGE(
453             "HANDLE", index, theHandle,
454             gHandleManagerPtr->getMinHandleNumber(),
455             gHandleManagerPtr->getMaxHandleNumber());
456 
457         if (!rc) handleList.push_back(theHandle);
458     }
459 
460     STAFString machine;
461 
462     for (index = 1, optionCount = parsedResult->optionTimes("MACHINE");
463          (index <= optionCount) && !rc; ++index)
464     {
465         rc = RESOLVE_INDEXED_STRING_OPTION("MACHINE", index, machine);
466         if (!rc) machineList.push_back(machine.toLowerCase());
467     }
468 
469     STAFString name;
470 
471     for (index = 1, optionCount = parsedResult->optionTimes("NAME");
472          (index <= optionCount) && !rc; ++index)
473     {
474         rc = RESOLVE_INDEXED_STRING_OPTION("NAME", index, name);
475         if (!rc) nameList.push_back(name.toLowerCase());
476     }
477 
478     STAFString user;
479 
480     for (index = 1, optionCount = parsedResult->optionTimes("USER");
481          (index <= optionCount) && !rc; ++index)
482     {
483         rc = RESOLVE_INDEXED_STRING_OPTION("USER", index, user);
484 
485         if (!rc)
486         {
487             // Check if authenticator was specified in the user value
488 
489             unsigned int sepIndex = user.find(gSpecSeparator);
490 
491             if (sepIndex == STAFString::kNPos)
492             {
493                 // No authenticator specified
494                 // Use lower-cased default authenticator
495                 user = gServiceManagerPtr->getDefaultAuthenticator().
496                     toLowerCase() + gSpecSeparator + user;
497             }
498             else
499             {
500                 // User specified in form of Authenticator://UserIdentifier
501                 // Change authenticator to lower-case.
502                 user = user.subString(0, sepIndex).toLowerCase() +
503                        user.subString(sepIndex);
504             }
505 
506             userList.push_back(user);
507         }
508     }
509 
510     STAFString type;
511 
512     for (index = 1, optionCount = parsedResult->optionTimes("TYPE");
513          (index <= optionCount) && !rc; ++index)
514     {
515         rc = RESOLVE_INDEXED_STRING_OPTION("TYPE", index, type);
516         if (!rc) typeList.push_back(type.toLowerCase());
517     }
518 
519     STAFString contains;
520 
521     for (index = 1, optionCount = parsedResult->optionTimes("CONTAINS");
522          (index <= optionCount) && !rc; ++index)
523     {
524         rc = RESOLVE_INDEXED_STRING_OPTION("CONTAINS", index, contains);
525         if (!rc) containsList.push_back(contains);
526     }
527 
528     STAFString icontains;
529 
530     for (index = 1, optionCount = parsedResult->optionTimes("ICONTAINS");
531          (index <= optionCount) && !rc; ++index)
532     {
533         rc = RESOLVE_INDEXED_STRING_OPTION("ICONTAINS", index, icontains);
534         if (!rc) icontainsList.push_back(icontains.toLowerCase());
535     }
536 
537     // Set the timeout variable.  If no WAIT option is specified, don't wait
538     // for a message to appear on the queue.
539 
540     unsigned int timeout = 0;
541 
542     if (!rc) rc = RESOLVE_DEFAULT_DURATION_OPTION(
543         "WAIT", timeout, STAF_EVENT_SEM_INDEFINITE_WAIT);
544 
545     if (rc) return STAFServiceResult(rc, errorBuffer);
546 
547     STAFHandleQueue::Message message;
548     unsigned int doWait = 0;
549     STAFEventSemPtr event;
550 
551     if (parsedResult->optionTimes("WAIT") != 0)
552     {
553         STAFMutexSemLock queueLock(handleQueue->fQueueSem);
554 
555         event = handleQueue->fNotify;
556         doWait = 1;
557     }
558 
559     STAFObjectPtr mc = STAFObject::createMarshallingContext();
560     mc->setMapClassDefinition(fQueueEntryMapClass->reference());
561 
562     STAFObjectPtr resultList;
563 
564     if (all | first)
565     {
566         // A list of queue elements that match the search criteria will
567         // be returned
568 
569         resultList = STAFObject::createList();
570     }
571 
572     // The number of elements in the queue that match the search criteria
573     unsigned int numFound = 0;
574 
575     STAFTimestamp startTime = STAFTimestamp::now();
576     unsigned int currTimeout = timeout;
577     bool retry = true;
578 
579     // We enter into a loop here waiting for one or more queue element(s)
580     // that match the search criteria to become available
581 
582     while (retry)
583     {
584         // Create a block so that the lock on the handle's queue is only
585         // held while within this block
586         {
587             // Get a lock on the handle's queue while getting/peeking
588             // messages from it
589 
590             STAFMutexSemLock queueLock(handleQueue->fQueueSem);
591 
592             bool done = false;  // Indicates if done iterating the queue
593 
594             // Used if isGet to keep track of the number of entries in the
595             // queue to skip since they have already been processed (to speed
596             // up things if not all queue elements match the criteria
597             unsigned int entriesToSkip = 0;
598 
599             while (!done && (all || (numFound < firstNum)))
600             {
601                 unsigned int foundIt = 0;
602 
603                 STAFHandleQueue::HandleQueue::iterator iter;
604                 unsigned int i = 0;
605                 bool readQueueFromBeginning = true;
606 
607                 for (iter = handleQueue->fQueue.begin();
608                      (iter != handleQueue->fQueue.end()) &&
609                       ((isGet && !foundIt) ||
610                        (!isGet && (all || (numFound < firstNum)))); ++iter)
611                 {
612                     if (isGet)
613                     {
614                         // Skip entries that we already know don't match
615 
616                         if (readQueueFromBeginning)
617                         {
618                             if (i < entriesToSkip)
619                             {
620                                 ++i;
621                                 continue;
622                             }
623                             else
624                             {
625                                 readQueueFromBeginning = false;
626                                 entriesToSkip = 0;
627                             }
628                         }
629                     }
630 
631                     foundIt = 1;
632 
633                     if (priorityList.size() != 0)
634                     {
635                         unsigned int checkPriority = iter->second.priority;
636 
637                         for (foundIt = 0, index = 0;
638                              index < priorityList.size(); ++index)
639                         {
640                             if (priorityList[index] == checkPriority)
641                                 foundIt = 1;
642                         }
643                     }
644 
645                     if (foundIt && (handleList.size() != 0))
646                     {
647                         STAFHandle_t checkHandle = iter->second.handle;
648 
649                         for (foundIt = 0, index = 0;
650                              index < handleList.size(); ++index)
651                         {
652                             if (handleList[index] == checkHandle)
653                                 foundIt = 1;
654                         }
655                     }
656 
657                     if (foundIt && (machineList.size() != 0))
658                     {
659                         STAFString lowerMachine = iter->second.machine.
660                             toLowerCase();
661 
662                         for (foundIt = 0, index = 0;
663                              index < machineList.size(); ++index)
664                         {
665                             // Do a wildcard match
666 
667                             if (lowerMachine.matchesWildcards(
668                                 machineList[index]))
669                             {
670                                 foundIt = 1;
671                             }
672                         }
673                     }
674 
675                     if (foundIt && (nameList.size() != 0))
676                     {
677                         STAFString lowerName =
678                             iter->second.process.toLowerCase();
679 
680                         for (foundIt = 0, index = 0;
681                              index < nameList.size(); ++index)
682                         {
683                             if (nameList[index] == lowerName)
684                                 foundIt = 1;
685                         }
686                     }
687 
688                     if (foundIt && (userList.size() != 0))
689                     {
690                         STAFString user =
691                             iter->second.authenticator.toLowerCase()+
692                             gSpecSeparator + iter->second.userIdentifier;
693 
694                         for (foundIt = 0, index = 0;
695                              index < userList.size(); ++index)
696                         {
697                             // Do a wildcard match
698 
699                             // if (user.matchesWildcards(userList[index]))
700                             if (userList[index] == user)
701                                 foundIt = 1;
702                         }
703                     }
704 
705                     if (foundIt && (typeList.size() != 0))
706                     {
707                         STAFString lowerType = iter->second.type.toLowerCase();
708 
709                         for (foundIt = 0, index = 0;
710                              index < typeList.size(); ++index)
711                         {
712                             if (typeList[index] == lowerType)
713                                 foundIt = 1;
714                         }
715                     }
716 
717                     if (foundIt && (containsList.size() != 0))
718                     {
719                         STAFString &msg = iter->second.message;
720 
721                         for (foundIt = 0, index = 0;
722                              index < containsList.size(); ++index)
723                         {
724                             if (msg.find(containsList[index]) !=
725                                 STAFString::kNPos)
726                             {
727                                 foundIt = 1;
728                             }
729                         }
730                     }
731 
732                     if (foundIt && (icontainsList.size() != 0))
733                     {
734                        STAFString lowerMsg = iter->second.message.
735                            toLowerCase();
736 
737                         for (foundIt = 0, index = 0;
738                              index < icontainsList.size(); ++index)
739                         {
740                             if (lowerMsg.find(icontainsList[index]) !=
741                                 STAFString::kNPos)
742                             {
743                                 foundIt = 1;
744                             }
745                         }
746                     }
747 
748                     if (!foundIt)
749                     {
750                         // This queue element doesn't match search criteria
751                         // so skip it next time if doing a GET request
752 
753                         if (isGet) ++entriesToSkip;
754 
755                         // Continue to process the next element in the queue
756                         continue;
757                     }
758 
759                     // This queue element matches the search criteria
760 
761                     numFound++;
762 
763                     // Create the queueEntryMap for the queued message
764 
765                     STAFObjectPtr queueEntryMap = fQueueEntryMapClass->
766                         createInstance();
767 
768                     queueEntryMap->put("priority",
769                                        STAFString(iter->second.priority));
770                     queueEntryMap->put("timestamp",
771                                        iter->second.timestamp.asString());
772                     queueEntryMap->put("machine", iter->second.machine);
773 
774                     if (iter->second.process.length() == 0)
775                     {
776                         queueEntryMap->put("handleName",
777                                            STAFObject::createNone());
778                     }
779                     else
780                     {
781                         queueEntryMap->put("handleName",
782                                            iter->second.process);
783                     }
784 
785                     queueEntryMap->put("handle",
786                                        STAFString(iter->second.handle));
787                     queueEntryMap->put("user",
788                                        iter->second.authenticator +
789                                        gSpecSeparator +
790                                        iter->second.userIdentifier);
791 
792                     if (iter->second.type.length() != 0)
793                         queueEntryMap->put("type", iter->second.type);
794 
795                     queueEntryMap->put("message", iter->second.message);
796 
797                     if (all || first)
798                         resultList->append(queueEntryMap);
799                     else
800                         mc->setRootObject(queueEntryMap);
801 
802                     if (isGet)
803                     {
804                         // Remove the message from the queue
805                         handleQueue->fQueue.erase(iter);
806                     }
807 
808                     if (!all && !first)
809                     {
810                         // Return information about this queue element
811                         return STAFServiceResult(kSTAFOk, mc->marshall());
812                     }
813 
814                     // If GET, break out of the for loop so that iter won't be
815                     // incremented at the end of the loop as that can cause an
816                     // exception since an element was removed from the
817                     // iterated queue list
818 
819                     if (isGet) break;
820 
821                 } // end for loop
822 
823                 if (!isGet)
824                 {
825                     // Peek - Finished iterating through the queue
826                     done = true;
827                 }
828                 else
829                 {
830                     // Get - Have to keep checking for matching messages
831                     //       if found a message last time since the message
832                     //       was removed and can't continue using the iterator
833                     //       for a list that has changed
834 
835                     if (!foundIt)
836                     {
837                         // No more matching messages in the queue
838                         done = true;
839                     }
840                 }
841             } // end while loop
842 
843             if (doWait && (numFound == 0))
844             {
845                 // WAIT option was specified and no matching queue elements
846                 // have been found yet.  Check if should continue waiting.
847 
848                 unsigned int deltaTime = (STAFTimestamp::now() - startTime) *
849                     1000;
850 
851                 if (deltaTime >= timeout)
852                 {
853                     return STAFServiceResult(kSTAFTimeout);
854                 }
855                 else
856                 {
857                     currTimeout = timeout - deltaTime;
858                     event->reset();
859                 }
860             }
861             else
862             {
863                 retry = false;
864             }
865 
866         } // end lock on handle's queue
867 
868         if (retry)
869         {
870             // Check if the handle still exists in case it has been
871             // unregistered/deleted in which case we want to return a
872             // Request Cancelled error and stop waiting
873 
874             STAFHandleQueuePtr queuePtr;
875 
876             rc = gHandleManagerPtr->handleQueue(requestInfo.fHandle,
877                                                 queuePtr);
878 
879             if (rc == kSTAFHandleDoesNotExist)
880                 return STAFServiceResult(kSTAFRequestCancelled);
881 
882             // Wait until an element is placed on the queue or times out
883 
884             if (event->wait(currTimeout))
885             {
886                 return STAFServiceResult(kSTAFTimeout);
887             }
888         }
889     }
890 
891     if (numFound == 0)
892     {
893         return STAFServiceResult(kSTAFNoQueueElement);
894     }
895 
896     mc->setRootObject(resultList);
897     return STAFServiceResult(kSTAFOk, mc->marshall());
898 }
899 
900 
handleDelete(const STAFServiceRequest & requestInfo)901 STAFServiceResult STAFQueueService::handleDelete(
902     const STAFServiceRequest &requestInfo)
903 {
904     // Verify that this request came from the local machine
905     // No check of trust is needed since these commands are only valid
906     // with respect to the submitting process' queue so just set
907     // required trust level to 0.
908 
909     IVALIDATE_LOCAL_TRUST(0, "DELETE");
910 
911     // Parse the request
912 
913     STAFCommandParseResultPtr parsedResult = fDeleteParser.parse(
914         requestInfo.fRequest);
915 
916     if (parsedResult->rc != kSTAFOk)
917     {
918         return STAFServiceResult(kSTAFInvalidRequestString,
919                                  parsedResult->errorBuffer, 0);
920     }
921 
922     STAFString errorBuffer;
923 
924     unsigned int checkPriority  = parsedResult->optionTimes("PRIORITY");
925     unsigned int checkMachine   = parsedResult->optionTimes("MACHINE");
926     unsigned int checkName      = parsedResult->optionTimes("NAME");
927     unsigned int checkHandle    = parsedResult->optionTimes("HANDLE");
928     unsigned int checkUser      = parsedResult->optionTimes("USER");
929     unsigned int checkType      = parsedResult->optionTimes("TYPE");
930     unsigned int checkContains  = parsedResult->optionTimes("CONTAINS");
931     unsigned int checkIContains = parsedResult->optionTimes("ICONTAINS");
932 
933     DEFINE_VAR_POOL_LIST(varPoolList, varPoolListSize, requestInfo);
934     STAFHandleQueuePtr handleQueue;
935     STAFRC_t rc = gHandleManagerPtr->handleQueue(requestInfo.fHandle,
936                                                  handleQueue);
937     if (rc) return STAFServiceResult(rc);
938 
939     unsigned int numDeleted = 0;
940     STAFMutexSemLock queueLock(handleQueue->fQueueSem);
941     STAFHandleQueue::HandleQueue::iterator iter;
942     int foundIt = 0;
943 
944     for (iter = handleQueue->fQueue.begin();
945          iter != handleQueue->fQueue.end();)
946     {
947         foundIt = 1;
948 
949         if (checkPriority)
950         {
951             unsigned int priority = 0;
952             foundIt = 0;
953 
954             for (int i = 1; (i <= parsedResult->optionTimes("PRIORITY")) &&
955                  !foundIt; ++i)
956             {
957                 rc = RESOLVE_INDEXED_UINT_OPTION("PRIORITY", i, priority);
958                 if (rc) return STAFServiceResult(rc, errorBuffer);
959                 if (priority == iter->second.priority) foundIt = 1;
960             }
961         }
962 
963         if (foundIt && checkMachine)
964         {
965             STAFString machine;
966             foundIt = 0;
967 
968             for (int i = 1; (i <= parsedResult->optionTimes("MACHINE")) &&
969                  !foundIt; ++i)
970             {
971                 rc = RESOLVE_INDEXED_STRING_OPTION("MACHINE", i, machine);
972 
973                 if (rc) return STAFServiceResult(rc, errorBuffer);
974 
975                 machine.lowerCase();
976 
977                 // Do a wildcard match
978 
979                 STAFString lowerMachine = iter->second.machine.toLowerCase();
980 
981                 if (lowerMachine.matchesWildcards(machine))
982                 {
983                     foundIt = 1;
984                 }
985             }
986         }
987 
988         if (foundIt && checkName)
989         {
990             STAFString name;
991             foundIt = 0;
992 
993             for (int i = 1; (i <= parsedResult->optionTimes("NAME")) &&
994                  !foundIt; ++i)
995             {
996                 rc = RESOLVE_INDEXED_STRING_OPTION("NAME", i, name);
997 
998                 if (rc) return STAFServiceResult(rc, errorBuffer);
999 
1000                 name.lowerCase();
1001 
1002                 if (name == iter->second.process.toLowerCase()) foundIt = 1;
1003             }
1004         }
1005 
1006         if (foundIt && checkHandle)
1007         {
1008             unsigned int theHandle = 0;
1009             foundIt = 0;
1010 
1011             for (int i = 1; (i <= parsedResult->optionTimes("HANDLE")) &&
1012                  !foundIt; ++i)
1013             {
1014                 rc = RESOLVE_INDEXED_UINT_OPTION_RANGE(
1015                     "HANDLE", i, theHandle,
1016                     gHandleManagerPtr->getMinHandleNumber(),
1017                     gHandleManagerPtr->getMaxHandleNumber());
1018 
1019                 if (rc) return STAFServiceResult(rc, errorBuffer);
1020 
1021                 if (theHandle == iter->second.handle) foundIt = 1;
1022             }
1023         }
1024 
1025         if (foundIt && checkUser)
1026         {
1027             STAFString user;
1028             foundIt = 0;
1029 
1030             for (int i = 1; (i <= parsedResult->optionTimes("USER")) &&
1031                  !foundIt; ++i)
1032             {
1033                 rc = RESOLVE_INDEXED_STRING_OPTION("USER", i, user);
1034 
1035                 if (rc) return STAFServiceResult(rc, errorBuffer);
1036 
1037                 // Check if authenticator was specified in the user value
1038 
1039                 unsigned int sepIndex = user.find(gSpecSeparator);
1040 
1041                 if (sepIndex == STAFString::kNPos)
1042                 {
1043                     // No authenticator specified
1044                     // Use lower-case default authenticator
1045                     user = gServiceManagerPtr->getDefaultAuthenticator().
1046                         toLowerCase() + gSpecSeparator + user;
1047                 }
1048                 else
1049                 {
1050                     // User specified in form of Authenticator://UserIdentifier
1051                     // Change authenticator to lower-case.
1052                     user = user.subString(0, sepIndex).toLowerCase() +
1053                            user.subString(sepIndex);
1054                 }
1055 
1056                 // Do a wildcard match
1057 
1058                 STAFString matchString(
1059                     iter->second.authenticator.toLowerCase() +
1060                     gSpecSeparator + iter->second.userIdentifier);
1061 
1062                 // if (matchString.matchesWildcards(user)) foundIt = 1;
1063                 if (matchString == user) foundIt = 1;
1064             }
1065         }
1066 
1067         if (foundIt && checkType)
1068         {
1069             STAFString type;
1070             foundIt = 0;
1071 
1072             for (int i = 1; (i <= parsedResult->optionTimes("TYPE")) &&
1073                  !foundIt; ++i)
1074             {
1075                 rc = RESOLVE_INDEXED_STRING_OPTION("TYPE", i, type);
1076 
1077                 if (rc) return STAFServiceResult(rc, errorBuffer);
1078 
1079                 type.lowerCase();
1080 
1081                 if (type == iter->second.type.toLowerCase()) foundIt = 1;
1082             }
1083         }
1084 
1085         if (foundIt && checkContains)
1086         {
1087             STAFString contains;
1088             foundIt = 0;
1089 
1090             for (int i = 1; (i <= parsedResult->optionTimes("CONTAINS")) &&
1091                  !foundIt; ++i)
1092             {
1093                 rc = RESOLVE_INDEXED_STRING_OPTION("CONTAINS", i, contains);
1094 
1095                 if (rc) return STAFServiceResult(rc, errorBuffer);
1096 
1097                 if (iter->second.message.find(contains) != STAFString::kNPos)
1098                     foundIt = 1;
1099             }
1100         }
1101 
1102         if (foundIt && checkIContains)
1103         {
1104             STAFString checkMessage = iter->second.message.toLowerCase();
1105             STAFString icontains;
1106             foundIt = 0;
1107 
1108             for (int i = 1; (i <= parsedResult->optionTimes("ICONTAINS")) &&
1109                  !foundIt; ++i)
1110             {
1111                 rc = RESOLVE_INDEXED_STRING_OPTION("ICONTAINS", i, icontains);
1112 
1113                 if (rc) return STAFServiceResult(rc, errorBuffer);
1114 
1115                 if (checkMessage.find(icontains.toLowerCase()) !=
1116                     STAFString::kNPos)
1117                 {
1118                     foundIt = 1;
1119                 }
1120             }
1121         }
1122 
1123         if (foundIt)
1124         {
1125             ++numDeleted;
1126             handleQueue->fQueue.erase(iter);
1127             iter = handleQueue->fQueue.begin();
1128         }
1129         else
1130         {
1131             ++iter;
1132         }
1133     }
1134 
1135     return STAFServiceResult(kSTAFOk, STAFString(numDeleted));
1136 }
1137 
1138 
handleList(const STAFServiceRequest & requestInfo)1139 STAFServiceResult STAFQueueService::handleList(
1140     const STAFServiceRequest &requestInfo)
1141 {
1142     // Verify that the requesting machine/user has at least trust level 2
1143 
1144     IVALIDATE_TRUST(2, "LIST");
1145 
1146     // Parse the request
1147 
1148     STAFCommandParseResultPtr parsedResult = fListParser.parse(
1149         requestInfo.fRequest);
1150 
1151     if (parsedResult->rc != kSTAFOk)
1152     {
1153         return STAFServiceResult(kSTAFInvalidRequestString,
1154                                  parsedResult->errorBuffer, 0);
1155     }
1156 
1157     STAFString errorBuffer;
1158 
1159     // HANDLE may only default if the request came from this machine
1160 
1161     if ((parsedResult->optionTimes("HANDLE") == 0) &&
1162         !requestInfo.fIsLocalRequest)
1163     {
1164         return STAFServiceResult(kSTAFInvalidRequestString);
1165     }
1166 
1167     DEFINE_VAR_POOL_LIST(varPoolList, varPoolListSize, requestInfo);
1168     unsigned int theHandle = requestInfo.fHandle;
1169 
1170     STAFRC_t rc = RESOLVE_OPTIONAL_UINT_OPTION_RANGE(
1171         "HANDLE", theHandle, gHandleManagerPtr->getMinHandleNumber(),
1172         gHandleManagerPtr->getMaxHandleNumber());
1173 
1174     if (rc) return STAFServiceResult(rc, errorBuffer);
1175 
1176     STAFHandleQueuePtr handleQueue;
1177 
1178     rc = gHandleManagerPtr->handleQueue(theHandle, handleQueue);
1179 
1180     if (rc) return STAFServiceResult(rc);
1181 
1182     // Create a marshalled list of maps containing information for entries
1183     // found in the queue
1184 
1185     STAFObjectPtr mc = STAFObject::createMarshallingContext();
1186     mc->setMapClassDefinition(fQueueEntryMapClass->reference());
1187     STAFObjectPtr queueList = STAFObject::createList();
1188 
1189     // Iterate through the queue
1190 
1191     STAFMutexSemLock queueLock(handleQueue->fQueueSem);
1192 
1193     STAFHandleQueue::HandleQueue::iterator iter;
1194 
1195     for (iter = handleQueue->fQueue.begin();
1196          iter != handleQueue->fQueue.end(); iter++)
1197     {
1198         STAFHandleQueue::Message message = iter->second;
1199 
1200         // Create a map for each entry in the queue
1201 
1202         STAFObjectPtr queueEntryMap = fQueueEntryMapClass->createInstance();
1203 
1204         queueEntryMap->put("priority", STAFString(message.priority));
1205         queueEntryMap->put("timestamp", message.timestamp.asString());
1206         queueEntryMap->put("machine", message.machine);
1207 
1208         if (message.process.length() == 0)
1209             queueEntryMap->put("handleName", STAFObject::createNone());
1210         else
1211             queueEntryMap->put("handleName", message.process);
1212 
1213         queueEntryMap->put("handle", STAFString(message.handle));
1214         queueEntryMap->put("user", message.authenticator +
1215                            gSpecSeparator + message.userIdentifier);
1216 
1217         if (message.type.length() != 0)
1218             queueEntryMap->put("type", message.type);
1219 
1220         queueEntryMap->put("message",
1221                            STAFHandle::maskPrivateData(message.message));
1222 
1223         queueList->append(queueEntryMap);
1224     }
1225 
1226     // Set the marshalling context's root object
1227 
1228     mc->setRootObject(queueList);
1229 
1230     return STAFServiceResult(rc, mc->marshall());
1231 }
1232 
1233 
handleHelp(const STAFServiceRequest & requestInfo)1234 STAFServiceResult STAFQueueService::handleHelp(
1235     const STAFServiceRequest &requestInfo)
1236 {
1237     // Verify that the requesting machine/user has at least trust level 1
1238 
1239     IVALIDATE_TRUST(1, "HELP");
1240 
1241     return STAFServiceResult(kSTAFOk, sHelpMsg);
1242 }
1243