1 /*****************************************************************************/ 2 /* Software Testing Automation Framework (STAF) */ 3 /* (C) Copyright IBM Corp. 2002, 2004 */ 4 /* */ 5 /* This software is licensed under the Eclipse Public License (EPL) V1.0. */ 6 /*****************************************************************************/ 7 8 package com.ibm.staf.service.stax; 9 import org.w3c.dom.Node; 10 import org.w3c.dom.NamedNodeMap; 11 import org.w3c.dom.NodeList; 12 import com.ibm.staf.*; 13 import com.ibm.staf.service.*; 14 import java.util.Map; 15 import java.util.TreeMap; 16 import java.util.HashMap; 17 import java.util.List; 18 import java.util.ArrayList; 19 import java.util.Iterator; 20 import java.util.Vector; 21 22 public class STAXProcessActionFactory implements STAXActionFactory, 23 STAXSTAFQueueListener, 24 STAXListRequestHandler, 25 STAXQueryRequestHandler, 26 STAXGenericRequestHandler, 27 STAXJobManagementHandler 28 { 29 static boolean debug = false; 30 31 static final String STAX_PROCESS_EVENT = new String("Process"); 32 33 static final String sProcessInfoMapClassName = new String( 34 "STAF/Service/STAX/ProcessInfo"); 35 static final String sQueryProcessMapClassName = new String( 36 "STAF/Service/STAX/QueryProcess"); 37 38 // Constructor 39 STAXProcessActionFactory(STAX staxService)40 public STAXProcessActionFactory(STAX staxService) 41 { 42 staxService.registerListHandler("PROCESSES", this); 43 staxService.registerQueryHandler("PROCESS", "Location:Handle", this); 44 staxService.registerJobManagementHandler(this); 45 46 // Set up parser that supports stopping a process or a testcase to 47 // determine if it is a STOP PROCESS or a STOP TESTCASE request 48 49 fStopGenericParser.addOption("STOP", 1, 50 STAFCommandParser.VALUENOTALLOWED); 51 fStopGenericParser.addOption("JOB", 1, 52 STAFCommandParser.VALUEREQUIRED); 53 fStopGenericParser.addOption("PROCESS", 1, 54 STAFCommandParser.VALUEREQUIRED); 55 fStopGenericParser.addOption("TESTCASE", 1, 56 STAFCommandParser.VALUEREQUIRED); 57 fStopGenericParser.addOption("KEY", 1, 58 STAFCommandParser.VALUEREQUIRED); 59 60 fStopGenericParser.addOptionNeed("STOP", "JOB"); 61 fStopGenericParser.addOptionNeed("JOB", "PROCESS TESTCASE"); 62 fStopGenericParser.addOptionNeed("KEY", "TESTCASE"); 63 64 fStopGenericParser.addOptionGroup("PROCESS TESTCASE", 0, 1); 65 66 // Set up Process Stop parser 67 68 fStopParser.addOption("STOP", 1, 69 STAFCommandParser.VALUENOTALLOWED); 70 fStopParser.addOption("JOB", 1, 71 STAFCommandParser.VALUEREQUIRED); 72 fStopParser.addOption("PROCESS", 1, 73 STAFCommandParser.VALUEREQUIRED); 74 75 fStopParser.addOptionNeed("STOP", "JOB"); 76 fStopParser.addOptionNeed("JOB", "PROCESS"); 77 78 // Construct map-class for list process information 79 80 fProcessInfoMapClass = new STAFMapClassDefinition( 81 sProcessInfoMapClassName); 82 83 fProcessInfoMapClass.addKey("processName", "Process Name"); 84 fProcessInfoMapClass.addKey("location", "Location"); 85 fProcessInfoMapClass.addKey("handle", "Handle"); 86 fProcessInfoMapClass.addKey("command", "Command"); 87 fProcessInfoMapClass.addKey("parms", "Parms"); 88 89 // Construct map-class for query process information 90 91 fQueryProcessMapClass = new STAFMapClassDefinition( 92 sQueryProcessMapClassName); 93 94 fQueryProcessMapClass.addKey("processName", "Process Name"); 95 fQueryProcessMapClass.addKey("location", "Location"); 96 fQueryProcessMapClass.addKey("handle", "Handle"); 97 fQueryProcessMapClass.addKey("blockName", "Block Name"); 98 fQueryProcessMapClass.addKey("threadID", "Thread ID"); 99 fQueryProcessMapClass.addKey("startTimestamp", "Start Date-Time"); 100 fQueryProcessMapClass.addKey("command", "Command"); 101 fQueryProcessMapClass.addKey("commandMode", "Command Mode"); 102 fQueryProcessMapClass.addKey("commandShell", "Command Shell"); 103 fQueryProcessMapClass.addKey("parms", "Parms"); 104 fQueryProcessMapClass.addKey("title", "Title"); 105 fQueryProcessMapClass.addKey("workdir", "Workdir"); 106 fQueryProcessMapClass.addKey("workload", "Workload"); 107 fQueryProcessMapClass.addKey("varList", "Vars"); 108 fQueryProcessMapClass.addKey("envList", "Envs"); 109 fQueryProcessMapClass.addKey("useProcessVars", "Use Process Vars"); 110 fQueryProcessMapClass.addKey("userName", "User Name"); 111 fQueryProcessMapClass.addKey("password", "Password"); 112 fQueryProcessMapClass.addKey("disabledAuth", "Disabled Auth"); 113 fQueryProcessMapClass.addKey("stdin", "Stdin"); 114 fQueryProcessMapClass.addKey("stdoutMode", "Stdout Mode"); 115 fQueryProcessMapClass.addKey("stdoutFile", "Stdout File"); 116 fQueryProcessMapClass.addKey("stderrMode", "Stderr Mode"); 117 fQueryProcessMapClass.addKey("stderrFile", "Stderr File"); 118 fQueryProcessMapClass.addKey("returnStdout", "Return Stdout"); 119 fQueryProcessMapClass.addKey("returnStderr", "Return Stderr"); 120 fQueryProcessMapClass.addKey("returnFileList", "Returned Files"); 121 fQueryProcessMapClass.addKey("stopUsing", "Stop Using"); 122 fQueryProcessMapClass.addKey("console", "Console"); 123 fQueryProcessMapClass.addKey("focus", "Focus"); 124 fQueryProcessMapClass.addKey("staticHandleName", "Static Handle Name"); 125 fQueryProcessMapClass.addKey("other", "Other"); 126 127 // Register as a GenericRequestHandler 128 try 129 { 130 // Assign STAFServiceInterfaceLevel class that this handler uses 131 132 Class serviceInterfaceClass = Class.forName(STAX.INTERFACE_LEVEL_30); 133 134 int rc = staxService.registerGenericRequestHandler( 135 this, serviceInterfaceClass); 136 137 if (rc != 0) 138 { 139 STAX.logToJVMLog( 140 "Error", "STAXProcessActionFactory: " + 141 "registerGenericRequestHandler() failed"); 142 } 143 } 144 catch (ClassNotFoundException e) 145 { 146 STAX.logToJVMLog( 147 "Error", "STAXProcessActionFactory: " + 148 "registerGenericRequestHandler: " + e); 149 } 150 } 151 getName()152 public String getName() { return fName; } 153 154 // STAXActionFactory methods 155 getDTDInfo()156 public String getDTDInfo() 157 { 158 return fDTDInfo; 159 } 160 getDTDTaskName()161 public String getDTDTaskName() 162 { 163 return "process"; 164 } 165 parseAction(STAX staxService, STAXJob job, org.w3c.dom.Node root)166 public STAXAction parseAction(STAX staxService, STAXJob job, 167 org.w3c.dom.Node root) throws STAXException 168 { 169 STAXProcessAction process = new STAXProcessAction(); 170 171 process.setActionFactory(this); 172 process.setLineNumber(root); 173 process.setXmlFile(job.getXmlFile()); 174 process.setXmlMachine(job.getXmlMachine()); 175 176 NamedNodeMap rootAttrs = root.getAttributes(); 177 178 for (int i = 0; i < rootAttrs.getLength(); ++i) 179 { 180 Node thisAttr = rootAttrs.item(i); 181 182 process.setElementInfo(new STAXElementInfo( 183 root.getNodeName(), thisAttr.getNodeName())); 184 185 if (thisAttr.getNodeName().equals("name")) 186 { 187 process.setName( 188 STAXUtil.parseAndCompileForPython( 189 thisAttr.getNodeValue(), process)); 190 } 191 } 192 193 NodeList children = root.getChildNodes(); 194 195 for (int i = 0; i < children.getLength(); ++i) 196 { 197 Node thisChild = children.item(i); 198 199 if (thisChild.getNodeType() == Node.COMMENT_NODE) 200 { 201 /* Do nothing */ 202 } 203 else if (thisChild.getNodeType() == Node.ELEMENT_NODE) 204 { 205 if (thisChild.getNodeName().equals("envs")) 206 process.setLineNumber(thisChild, "env"); 207 else if (thisChild.getNodeName().equals("vars")) 208 process.setLineNumber(thisChild, "var"); 209 else if (thisChild.getNodeName().equals("returnfiles")) 210 process.setLineNumber(thisChild, "returnfile"); 211 else 212 process.setLineNumber(thisChild); 213 214 if (thisChild.getNodeName().equals("location")) 215 { 216 process.setLocation(handleChild(thisChild, process)); 217 } 218 else if (thisChild.getNodeName().equals("command")) 219 { 220 NamedNodeMap attrs = thisChild.getAttributes(); 221 222 for (int j = 0; j < attrs.getLength(); ++j) 223 { 224 Node thisAttr = attrs.item(j); 225 226 process.setElementInfo(new STAXElementInfo( 227 thisChild.getNodeName(), thisAttr.getNodeName())); 228 229 if (thisAttr.getNodeName().equals("mode")) 230 { 231 String mode = STAXUtil.parseAndCompileForPython( 232 thisAttr.getNodeValue(), process); 233 234 process.setCommandMode(mode); 235 } 236 else if (thisAttr.getNodeName().equals("shell")) 237 { 238 String shell = STAXUtil.parseAndCompileForPython( 239 thisAttr.getNodeValue(), process); 240 241 process.setCommandShell(shell); 242 } 243 } 244 245 process.setCommand(handleChild(thisChild, process)); 246 } 247 else if (thisChild.getNodeName().equals("workload")) 248 { 249 process.setWorkload( 250 handleChild(thisChild, process), 251 handleIfAttribute(thisChild, process)); 252 } 253 else if (thisChild.getNodeName().equals("title")) 254 { 255 process.setTitle( 256 handleChild(thisChild, process), 257 handleIfAttribute(thisChild, process)); 258 } 259 else if (thisChild.getNodeName().equals("parms")) 260 { 261 process.setParms( 262 handleChild(thisChild, process), 263 handleIfAttribute(thisChild, process)); 264 } 265 else if (thisChild.getNodeName().equals("workdir")) 266 { 267 process.setWorkdir( 268 handleChild(thisChild, process), 269 handleIfAttribute(thisChild, process)); 270 } 271 else if (thisChild.getNodeName().equals("vars")) 272 { 273 process.setVars( 274 handleChild(thisChild, process, "var"), 275 handleIfAttribute(thisChild, process, "var")); 276 } 277 else if (thisChild.getNodeName().equals("var")) 278 { 279 process.setVars( 280 handleChild(thisChild, process), 281 handleIfAttribute(thisChild, process)); 282 } 283 else if (thisChild.getNodeName().equals("envs")) 284 { 285 process.setEnvs( 286 handleChild(thisChild, process, "env"), 287 handleIfAttribute(thisChild, process, "env")); 288 } 289 else if (thisChild.getNodeName().equals("env")) 290 { 291 process.setEnvs( 292 handleChild(thisChild, process), 293 handleIfAttribute(thisChild, process)); 294 } 295 else if (thisChild.getNodeName().equals("useprocessvars")) 296 { 297 process.setUseprocessvars( 298 "useprocessvars", 299 handleIfAttribute(thisChild, process)); 300 } 301 else if (thisChild.getNodeName().equals("stopusing")) 302 { 303 process.setStopusing( 304 handleChild(thisChild, process), 305 handleIfAttribute(thisChild, process)); 306 } 307 else if (thisChild.getNodeName().equals("console")) 308 { 309 String ifValue = new String(); 310 String useValue = new String(); 311 312 NamedNodeMap attrs = thisChild.getAttributes(); 313 314 for (int j = 0; j < attrs.getLength(); ++j) 315 { 316 Node thisAttr = attrs.item(j); 317 318 process.setElementInfo(new STAXElementInfo( 319 thisChild.getNodeName(), thisAttr.getNodeName())); 320 321 if (thisAttr.getNodeName().equals("if")) 322 ifValue = STAXUtil.parseAndCompileForPython( 323 thisAttr.getNodeValue(), process); 324 else if (thisAttr.getNodeName().equals("use")) 325 useValue = STAXUtil.parseAndCompileForPython( 326 thisAttr.getNodeValue(), process); 327 } 328 329 process.setConsole(useValue, ifValue); 330 } 331 else if (thisChild.getNodeName().equals("focus")) 332 { 333 String ifValue = new String(); 334 String modeValue = new String(); 335 336 NamedNodeMap attrs = thisChild.getAttributes(); 337 338 for (int j = 0; j < attrs.getLength(); ++j) 339 { 340 Node thisAttr = attrs.item(j); 341 342 process.setElementInfo(new STAXElementInfo( 343 thisChild.getNodeName(), thisAttr.getNodeName())); 344 345 if (thisAttr.getNodeName().equals("if")) 346 ifValue = STAXUtil.parseAndCompileForPython( 347 thisAttr.getNodeValue(), process); 348 else if (thisAttr.getNodeName().equals("mode")) 349 modeValue = STAXUtil.parseAndCompileForPython( 350 thisAttr.getNodeValue(), process); 351 } 352 353 process.setFocus(modeValue, ifValue); 354 } 355 else if (thisChild.getNodeName().equals("username")) 356 { 357 process.setUsername( 358 handleChild(thisChild, process), 359 handleIfAttribute(thisChild, process)); 360 } 361 else if (thisChild.getNodeName().equals("password")) 362 { 363 process.setPassword( 364 handleChild(thisChild, process), 365 handleIfAttribute(thisChild, process)); 366 } 367 else if (thisChild.getNodeName().equals("disabledauth")) 368 { 369 String ifValue = new String(); 370 String actionValue = new String(); 371 372 NamedNodeMap attrs = thisChild.getAttributes(); 373 374 for (int j = 0; j < attrs.getLength(); ++j) 375 { 376 Node thisAttr = attrs.item(j); 377 378 process.setElementInfo(new STAXElementInfo( 379 thisChild.getNodeName(), thisAttr.getNodeName())); 380 381 if (thisAttr.getNodeName().equals("if")) 382 ifValue = STAXUtil.parseAndCompileForPython( 383 thisAttr.getNodeValue(), process); 384 else if (thisAttr.getNodeName().equals("action")) 385 actionValue = STAXUtil.parseAndCompileForPython( 386 thisAttr.getNodeValue(), process); 387 } 388 389 process.setDisabledauth(actionValue, ifValue); 390 } 391 else if (thisChild.getNodeName().equals("statichandlename")) 392 { 393 process.setStatichandlename( 394 handleChild(thisChild, process), 395 handleIfAttribute(thisChild, process)); 396 } 397 else if (thisChild.getNodeName().equals("stdin")) 398 { 399 process.setStdin( 400 handleChild(thisChild, process), 401 handleIfAttribute(thisChild, process)); 402 } 403 else if (thisChild.getNodeName().equals("stdout")) 404 { 405 String ifValue = new String(); 406 String modeValue = new String(); 407 408 NamedNodeMap attrs = thisChild.getAttributes(); 409 410 for (int j = 0; j < attrs.getLength(); ++j) 411 { 412 Node thisAttr = attrs.item(j); 413 414 process.setElementInfo(new STAXElementInfo( 415 thisChild.getNodeName(), thisAttr.getNodeName())); 416 417 if (thisAttr.getNodeName().equals("if")) 418 ifValue = STAXUtil.parseAndCompileForPython( 419 thisAttr.getNodeValue(), process); 420 else if (thisAttr.getNodeName().equals("mode")) 421 modeValue = STAXUtil.parseAndCompileForPython( 422 thisAttr.getNodeValue(), process); 423 } 424 425 process.setStdout(handleChild(thisChild, process), 426 modeValue, ifValue); 427 } 428 else if (thisChild.getNodeName().equals("stderr")) 429 { 430 String ifValue = new String(); 431 String modeValue = new String(); 432 433 NamedNodeMap attrs = thisChild.getAttributes(); 434 435 for (int j = 0; j < attrs.getLength(); ++j) 436 { 437 Node thisAttr = attrs.item(j); 438 439 process.setElementInfo(new STAXElementInfo( 440 thisChild.getNodeName(), thisAttr.getNodeName())); 441 442 if (thisAttr.getNodeName().equals("if")) 443 ifValue = STAXUtil.parseAndCompileForPython( 444 thisAttr.getNodeValue(), process); 445 else if (thisAttr.getNodeName().equals("mode")) 446 modeValue = STAXUtil.parseAndCompileForPython( 447 thisAttr.getNodeValue(), process); 448 } 449 450 process.setStderr(handleChild(thisChild, process), 451 modeValue, ifValue); 452 } 453 else if (thisChild.getNodeName().equals("returnstdout")) 454 { 455 process.setReturnStdout( 456 "returnstdout", 457 handleIfAttribute(thisChild, process)); 458 } 459 else if (thisChild.getNodeName().equals("returnstderr")) 460 { 461 process.setReturnStderr( 462 "returnstderr", 463 handleIfAttribute(thisChild, process)); 464 } 465 else if (thisChild.getNodeName().equals("returnfile")) 466 { 467 process.setReturnFiles( 468 handleChild(thisChild, process), 469 handleIfAttribute(thisChild, process)); 470 } 471 else if (thisChild.getNodeName().equals("returnfiles")) 472 { 473 process.setReturnFiles( 474 handleChild(thisChild, process, "returnfile"), 475 handleIfAttribute(thisChild, process, "returnfile")); 476 } 477 else if (thisChild.getNodeName().equals("other")) 478 { 479 process.setOther( 480 handleChild(thisChild, process), 481 handleIfAttribute(thisChild, process)); 482 } 483 else if (thisChild.getNodeName().equals("process-action")) 484 { 485 String ifValue = new String(); 486 487 NamedNodeMap attrs = thisChild.getAttributes(); 488 489 for (int j = 0; j < attrs.getLength(); ++j) 490 { 491 Node thisAttr = attrs.item(j); 492 493 process.setElementInfo(new STAXElementInfo( 494 thisChild.getNodeName(), thisAttr.getNodeName())); 495 496 if (thisAttr.getNodeName().equals("if")) 497 ifValue = STAXUtil.parseAndCompileForPython( 498 thisAttr.getNodeValue(), process); 499 } 500 501 NodeList processActionChildren = thisChild.getChildNodes(); 502 503 STAXAction processAction = null; 504 505 for (int j = 0; j < processActionChildren.getLength(); ++j) 506 { 507 Node processActionChild = 508 processActionChildren.item(j); 509 510 if (processActionChild.getNodeType() == 511 Node.COMMENT_NODE) 512 { 513 /* Do nothing */ 514 } 515 else if (processActionChild.getNodeType() == 516 Node.ELEMENT_NODE) 517 { 518 if (processAction != null) 519 { 520 process.setElementInfo( 521 new STAXElementInfo( 522 thisChild.getNodeName(), 523 STAXElementInfo.NO_ATTRIBUTE_NAME, 524 STAXElementInfo.LAST_ELEMENT_INDEX, 525 "Invalid element type \"" + 526 processActionChild.getNodeName() + 527 "\"")); 528 529 throw new STAXInvalidXMLElementCountException( 530 STAXUtil.formatErrorMessage(process), 531 process); 532 } 533 534 STAXActionFactory factory = 535 staxService.getActionFactory( 536 processActionChild.getNodeName()); 537 538 if (factory == null) 539 { 540 process.setElementInfo(new STAXElementInfo( 541 thisChild.getNodeName(), 542 STAXElementInfo.NO_ATTRIBUTE_NAME, 543 STAXElementInfo.LAST_ELEMENT_INDEX, 544 "No action factory for element type \"" + 545 processActionChild.getNodeName() + "\"")); 546 547 throw new STAXInvalidXMLElementException( 548 STAXUtil.formatErrorMessage(process), 549 process); 550 } 551 552 processAction = factory.parseAction(staxService, 553 job, processActionChild); 554 } 555 } 556 557 process.setProcessAction(processAction, ifValue); 558 } 559 } 560 else 561 { 562 process.setElementInfo(new STAXElementInfo( 563 root.getNodeName(), STAXElementInfo.NO_ATTRIBUTE_NAME, 564 STAXElementInfo.LAST_ELEMENT_INDEX, 565 "Contains invalid node type: " + 566 Integer.toString(thisChild.getNodeType()))); 567 568 throw new STAXInvalidXMLNodeTypeException( 569 STAXUtil.formatErrorMessage(process), process); 570 } 571 } 572 573 return process; 574 } 575 handleIfAttribute(Node thisChild, STAXProcessAction action)576 private String handleIfAttribute(Node thisChild, STAXProcessAction action) 577 throws STAXException 578 { 579 return handleIfAttribute(thisChild,action, thisChild.getNodeName()); 580 } 581 handleIfAttribute(Node thisChild, STAXProcessAction action, String elementName)582 private String handleIfAttribute(Node thisChild, STAXProcessAction action, 583 String elementName) 584 throws STAXException 585 { 586 String ifValue = new String(); 587 588 NamedNodeMap attrs = thisChild.getAttributes(); 589 590 for (int i = 0; i < attrs.getLength(); ++i) 591 { 592 Node thisAttr = attrs.item(i); 593 594 action.setElementInfo(new STAXElementInfo( 595 elementName, thisAttr.getNodeName(), 596 STAXElementInfo.LAST_ELEMENT_INDEX)); 597 598 if (thisAttr.getNodeName().equals("if")) 599 ifValue = STAXUtil.parseAndCompileForPython( 600 thisAttr.getNodeValue(), action); 601 } 602 603 return ifValue; 604 } 605 handleChild(Node root, STAXProcessAction action)606 private String handleChild(Node root, STAXProcessAction action) 607 throws STAXException 608 { 609 return handleChild(root, action, root.getNodeName()); 610 } 611 handleChild(Node root, STAXProcessAction action, String elementName)612 private String handleChild(Node root, STAXProcessAction action, 613 String elementName) 614 throws STAXException 615 { 616 NodeList children = root.getChildNodes(); 617 618 for (int i = 0; i < children.getLength(); ++i) 619 { 620 Node thisChild = children.item(i); 621 622 // XXX: Should I be able to have a COMMENT_NODE here? 623 624 if (thisChild.getNodeType() == Node.COMMENT_NODE) 625 { 626 /* Do nothing */ 627 } 628 else if (thisChild.getNodeType() == Node.TEXT_NODE) 629 { 630 action.setElementInfo(new STAXElementInfo( 631 elementName, STAXElementInfo.NO_ATTRIBUTE_NAME, 632 STAXElementInfo.LAST_ELEMENT_INDEX)); 633 634 return STAXUtil.parseAndCompileForPython( 635 thisChild.getNodeValue(), action); 636 } 637 else if (thisChild.getNodeType() == Node.CDATA_SECTION_NODE) 638 { 639 /* Do nothing */ 640 } 641 else 642 { 643 action.setElementInfo( 644 new STAXElementInfo( 645 elementName, STAXElementInfo.NO_ATTRIBUTE_NAME, 646 STAXElementInfo.LAST_ELEMENT_INDEX, 647 Integer.toString(thisChild.getNodeType()))); 648 649 throw new STAXInvalidXMLNodeTypeException( 650 STAXUtil.formatErrorMessage(action), action); 651 } 652 } 653 654 return new String(); 655 } 656 657 658 // STAXSTAFQueueListener methods 659 handleQueueMessage(STAXSTAFMessage message, STAXJob job)660 public void handleQueueMessage(STAXSTAFMessage message, STAXJob job) 661 { 662 // XXX: How to make sure that the machine they registered 663 // with is the machine on the queue (long vs. short 664 // names)? Maybe try 665 // a.startsWith(b) || b.startsWith(a) 666 667 String machine = message.getMachine(); 668 int handle = message.getProcessHandle(); 669 670 String key = ""; 671 672 if (!message.getProcessKey().equals("")) 673 { 674 key = message.getProcessKey(); 675 } 676 else 677 { 678 // XXX Does lower casing the machine name cause any other problems? 679 key = (machine + "/" + handle).toLowerCase(); 680 } 681 682 @SuppressWarnings("unchecked") 683 HashMap<String, Object> processMap = 684 (HashMap<String, Object>)job.getData("processMap"); 685 686 if (processMap == null) 687 { 688 // Could occur if job is being terminated 689 return; 690 } 691 692 synchronized (processMap) 693 { 694 STAXProcessCompleteListener listener = 695 (STAXProcessCompleteListener)processMap.get(key); 696 697 if (listener != null) 698 { 699 if (debug) 700 { 701 STAX.logToJVMLog( 702 "Debug", job.getJobNumber(), 703 "ProcessActionFactory::handleQueueMessages() - " + 704 "Remove from processMap"); 705 } 706 707 listener.processComplete( 708 machine, handle, message.getProcessRC(), 709 message.getProcessResultAsList(), 710 message.getProcessTimestamp()); 711 712 processMap.remove(key); 713 } 714 else 715 { 716 // Log a warning message in the job log 717 718 if (debug) 719 { 720 String msg = "STAXProcessActionFactory.handle" + 721 "QueueMessage: No listener found for message:\n" + 722 STAFMarshallingContext.unmarshall( 723 message.getResult()).toString(); 724 725 msg += "\nCurrentKeys="; 726 727 Iterator iter = processMap.keySet().iterator(); 728 729 while (iter.hasNext()) 730 { 731 msg += iter.next() + ";"; 732 } 733 734 job.log(STAXJob.JOB_LOG, "warning", msg); 735 736 STAX.logToJVMLog( 737 "Debug", job.getJobNumber(), 738 "ProcessActionFactory::handleQueueMessages() - " + 739 "Add to processMap"); 740 } 741 742 // If we received the "process end" message before we placed 743 // the machine/handle in the process map, just save the key 744 // and the message in the process map. When STAXProcessAction 745 // receives the requestComplete message, since the key already 746 // exists, it will just remove it. 747 748 processMap.put(key.toLowerCase(), message); 749 } 750 } 751 } 752 753 754 // STAXJobManagement methods 755 initJob(STAXJob job)756 public void initJob(STAXJob job) 757 { 758 boolean result = job.setData("processMap", new HashMap<String, Object>()); 759 760 if (!result) 761 { 762 String msg = "STAXProcessActionFactory.initJob: setData for " + 763 "processMap failed."; 764 job.log(STAXJob.JOB_LOG, "error", msg); 765 } 766 767 result = job.setData("processRequestMap", 768 new TreeMap<String, STAXProcessAction>()); 769 770 if (!result) 771 { 772 String msg = "STAXProcessActionFactory.initJob: setData for " + 773 "processRequestMap failed."; 774 job.log(STAXJob.JOB_LOG, "error", msg); 775 } 776 777 job.registerSTAFQueueListener("STAF/Process/End", this); 778 } 779 terminateJob(STAXJob job)780 public void terminateJob(STAXJob job) 781 { /* Do Nothing */ } 782 783 784 // STAXListRequestHandler method 785 handleListRequest(String type, STAXJob job, STAXRequestSettings settings)786 public STAFResult handleListRequest(String type, STAXJob job, 787 STAXRequestSettings settings) 788 { 789 if (type.equalsIgnoreCase("processes")) 790 { 791 // LIST JOB <Job ID> PROCESSES 792 793 // Create the marshalling context and set its map class definitions 794 // and create an empty list to contain the block map entries 795 796 STAFMarshallingContext mc = new STAFMarshallingContext(); 797 mc.setMapClassDefinition(fProcessInfoMapClass); 798 List<Map<String, Object>> processOutputList = 799 new ArrayList<Map<String, Object>>(); 800 801 // Iterate through the process map, generating the output list 802 803 TreeMap processes = (TreeMap)job.getData("processRequestMap"); 804 805 if (processes != null) 806 { 807 synchronized (processes) 808 { 809 Iterator iter = processes.values().iterator(); 810 811 while (iter.hasNext()) 812 { 813 STAXProcessAction process = 814 (STAXProcessAction)iter.next(); 815 816 Map<String, Object> processMap = 817 new TreeMap<String, Object>(); 818 processMap.put("staf-map-class-name", 819 fProcessInfoMapClass.name()); 820 processMap.put("processName", process.getName()); 821 processMap.put("location", process.getLocation()); 822 processMap.put( 823 "handle", "" + process.getProcessHandle()); 824 processMap.put( 825 "command", STAFUtil.maskPrivateData( 826 process.getCommand())); 827 processMap.put( 828 "parms", STAFUtil.maskPrivateData( 829 process.getParms())); 830 831 processOutputList.add(processMap); 832 } 833 } 834 } 835 836 mc.setRootObject(processOutputList); 837 838 return new STAFResult(STAFResult.Ok, mc.marshall()); 839 } 840 else 841 return new STAFResult(STAFResult.DoesNotExist, type); 842 } 843 844 // STAXQueryRequestHandler methods 845 handleQueryRequest(String type, String key, STAXJob job, STAXRequestSettings settings)846 public STAFResult handleQueryRequest(String type, String key, STAXJob job, 847 STAXRequestSettings settings) 848 { 849 if (type.equalsIgnoreCase("process")) 850 { 851 // QUERY JOB <Job ID> PROCESS <Location:Handle> 852 853 // Create the marshalling context and set its map class definition 854 855 STAFMarshallingContext mc = new STAFMarshallingContext(); 856 mc.setMapClassDefinition(fQueryProcessMapClass); 857 858 key = key.toLowerCase(); 859 860 TreeMap processes = (TreeMap)job.getData("processRequestMap"); 861 862 if (processes == null) 863 return new STAFResult(STAFResult.DoesNotExist, key); 864 865 STAXProcessAction process = null; 866 867 synchronized (processes) 868 { 869 process = (STAXProcessAction)processes.get(key); 870 } 871 872 if (process == null) 873 return new STAFResult(STAFResult.DoesNotExist, key); 874 875 Map<String, Object> processMap = new TreeMap<String, Object>(); 876 processMap.put("staf-map-class-name", 877 fQueryProcessMapClass.name()); 878 processMap.put("processName", process.getName()); 879 processMap.put("location", process.getLocation()); 880 processMap.put("handle", "" + process.getProcessHandle()); 881 processMap.put("blockName", process.getCurrentBlockName()); 882 processMap.put("threadID", 883 "" + process.getThread().getThreadNumber()); 884 processMap.put("startTimestamp", process.getStartTimestamp(). 885 getTimestampString()); 886 processMap.put("command", 887 STAFUtil.maskPrivateData(process.getCommand())); 888 889 // The rest of the process elements are optional. 890 891 if (!process.getCommandMode().equals("")) 892 processMap.put("commandMode", process.getCommandMode()); 893 894 if (!process.getCommandShell().equals("")) 895 processMap.put("commandShell", process.getCommandShell()); 896 897 if (!process.getParms().equals("")) 898 processMap.put("parms", 899 STAFUtil.maskPrivateData(process.getParms())); 900 901 if (!process.getTitle().equals("")) 902 processMap.put("title", process.getTitle()); 903 904 if (!process.getWorkdir().equals("")) 905 processMap.put("workdir", process.getWorkdir()); 906 907 if (!process.getWorkload().equals("")) 908 processMap.put("workload", process.getWorkload()); 909 910 List<String> varList = new ArrayList<String>(); 911 Vector<String> vars = process.getVars(); 912 913 for (int i = 0; i < vars.size(); i++) 914 { 915 varList.add(vars.elementAt(i)); 916 } 917 918 processMap.put("varList", varList); 919 920 List<String> envList = new ArrayList<String>(); 921 Vector<String> envs = process.getEnvs(); 922 923 for (int i = 0; i < envs.size(); i++) 924 { 925 envList.add(envs.elementAt(i)); 926 } 927 928 processMap.put("envList", envList); 929 930 if (!process.getUseprocessvars().equals("")) 931 processMap.put("useProcessVars", "true"); 932 933 if (!process.getUsername().equals("")) 934 processMap.put("userName", process.getUsername()); 935 936 // Mask the true value for the password 937 if (!process.getPassword().equals("")) 938 processMap.put("password", "*******"); 939 940 if (!process.getDisabledauth().equals("")) 941 processMap.put("disabledAuth", process.getDisabledauth()); 942 943 if (!process.getStdin().equals("")) 944 processMap.put("stdin", process.getStdin()); 945 946 if (!process.getStdout().equals("")) 947 { 948 processMap.put("stdoutMode", process.getStdoutMode()); 949 processMap.put("stdoutFile", process.getStdout()); 950 } 951 952 if (!process.getStderr().equals("")) 953 processMap.put("stderrFile", process.getStderr()); 954 955 if (!process.getStderrMode().equals("")) 956 processMap.put("stderrMode", process.getStderrMode()); 957 958 if (!process.getReturnStdout().equals("")) 959 processMap.put("returnStdout", "true"); 960 961 if (!process.getReturnStderr().equals("")) 962 processMap.put("returnStderr", "true"); 963 964 List<String> returnFileList = new ArrayList<String>(); 965 Vector<String> returnfiles = process.getReturnFiles(); 966 967 for (int i = 0; i < returnfiles.size(); i++) 968 { 969 returnFileList.add(returnfiles.elementAt(i)); 970 } 971 972 processMap.put("returnFileList", returnFileList); 973 974 if (!process.getStopusing().equals("")) 975 processMap.put("stopUsing", process.getStopusing()); 976 977 if (!process.getConsole().equals("")) 978 processMap.put("console", process.getConsole()); 979 980 if (!process.getFocus().equals("")) 981 processMap.put("focus", process.getFocus()); 982 983 if (!process.getStatichandlename().equals("")) 984 processMap.put("staticHandleName", 985 process.getStatichandlename()); 986 987 if (!process.getOther().equals("")) 988 processMap.put("other", process.getOther()); 989 990 mc.setRootObject(processMap); 991 992 return new STAFResult(STAFResult.Ok, mc.marshall()); 993 } 994 else 995 return new STAFResult(STAFResult.DoesNotExist, type); 996 } 997 handleQueryJobRequest(STAXJob job, STAXRequestSettings settings)998 public STAFResult handleQueryJobRequest(STAXJob job, 999 STAXRequestSettings settings) 1000 { 1001 return new STAFResult(STAFResult.Ok, ""); 1002 } 1003 1004 // STAXGenericRequestHandler Interface Methods 1005 handleRequest(Object infoObject, STAX staxService)1006 public STAFResult handleRequest(Object infoObject, STAX staxService) 1007 { 1008 STAFServiceInterfaceLevel30.RequestInfo info = 1009 (STAFServiceInterfaceLevel30.RequestInfo)infoObject; 1010 1011 String lowerRequest = info.request.toLowerCase(); 1012 1013 if (lowerRequest.startsWith("stop")) 1014 { 1015 // Need to make sure that the STAXTestcaseActionFactory gets a 1016 // chance to handle a STOP TESTCASE request so using a parser 1017 // that supports either a STOP PROCESS or STOP TESTCASE request. 1018 1019 // XXX: A better way of determining if it is a STOP PROCESS or 1020 // STOP TESTCASE request would be nice because now if the syntax 1021 // of a STOP TESTCASE request changes, have to make the same 1022 // change to the fStopGenericParser here. 1023 1024 STAFCommandParseResult parseResult = fStopGenericParser.parse( 1025 info.request); 1026 1027 if (parseResult.rc != STAFResult.Ok) 1028 { 1029 return new STAFResult(STAFResult.InvalidRequestString, 1030 parseResult.errorBuffer); 1031 } 1032 1033 if (parseResult.optionTimes("TESTCASE") > 0) 1034 { 1035 // This is a STOP TESTCASE request, not a STOP PROCESS request. 1036 // Returning nothing in the result indicates that this parser 1037 // does not support this request. 1038 return new STAFResult(STAFResult.InvalidRequestString, ""); 1039 } 1040 1041 return handleStopRequest(info, staxService); 1042 } 1043 else 1044 { // Returning nothing in the result indicates that this parser 1045 // does not support this request. 1046 return new STAFResult(STAFResult.InvalidRequestString, ""); 1047 } 1048 } 1049 handleStopRequest( STAFServiceInterfaceLevel30.RequestInfo info, STAX staxService)1050 private STAFResult handleStopRequest( 1051 STAFServiceInterfaceLevel30.RequestInfo info, STAX staxService) 1052 { 1053 // Verify the requesting machine/user has at least trust level 5 1054 1055 STAFResult trustResult = STAFUtil.validateTrust( 1056 4, staxService.getServiceName(), "STOP", 1057 staxService.getLocalMachineName(), info); 1058 1059 if (trustResult.rc != STAFResult.Ok) return trustResult; 1060 1061 // Parse the request 1062 1063 STAFCommandParseResult parseResult= fStopParser.parse(info.request); 1064 1065 if (parseResult.rc != STAFResult.Ok) 1066 { 1067 return new STAFResult(STAFResult.InvalidRequestString, 1068 parseResult.errorBuffer); 1069 } 1070 1071 // Resolve the value specified for JOB and get its integer value 1072 1073 STAFResult res = STAFUtil.resolveRequestVarAndCheckInt( 1074 "JOB", parseResult.optionValue("JOB"), 1075 staxService.getSTAFHandle(), info.requestNumber); 1076 1077 if (res.rc != 0) return res; 1078 1079 Integer jobID = new Integer(res.result); 1080 1081 // Verify that the JOB ID is a currently active job 1082 1083 STAXJob job = null; 1084 1085 job = (STAXJob)staxService.getJobMap().get(jobID); 1086 1087 if (job == null) 1088 { 1089 return new STAFResult( 1090 STAFResult.DoesNotExist, 1091 "Job " + jobID + " is not currently running."); 1092 } 1093 1094 // Resolve the value specified for PROCESS 1095 1096 res = STAFUtil.resolveRequestVar( 1097 parseResult.optionValue("PROCESS"), 1098 staxService.getSTAFHandle(), info.requestNumber); 1099 1100 if (res.rc != 0) return res; 1101 1102 String processKey = res.result; 1103 1104 // Verify that the process is a currently active process 1105 // (according to STAX) 1106 1107 STAXProcessAction processAction = null; 1108 TreeMap processes = (TreeMap)job.getData("processRequestMap"); 1109 1110 if (processes != null) 1111 { 1112 synchronized (processes) 1113 { 1114 processAction = (STAXProcessAction)processes.get(processKey); 1115 } 1116 } 1117 1118 if (processAction == null) 1119 { 1120 return new STAFResult( 1121 STAFResult.DoesNotExist, 1122 "The specified process (" + processKey + ") does not exist." + 1123 " Note its format must be: <location>:<handle#>"); 1124 } 1125 1126 String location = processAction.getLocation(); 1127 int processHandle = processAction.getProcessHandle(); 1128 1129 long processRC = 0; // Assume 0 if cannot obtain 1130 String stopTimestamp = ""; 1131 1132 // Stop the STAF process (if still running) by submitting a 1133 // PROCESS STOP HANDLE request on the machine where the process is 1134 // running. 1135 1136 res = job.submitSync( 1137 location, "PROCESS", "QUERY HANDLE " + processHandle); 1138 1139 if (debug) 1140 { 1141 STAX.logToJVMLog( 1142 "Debug", job.getJobNumber(), 1143 "STAXProcessActionFactory::handleStopRequest: " + 1144 "PROCESS QUERY HANDLE " + processHandle + ", RC=" + res.rc); 1145 } 1146 1147 if (res.rc == STAFResult.Ok) 1148 { 1149 // If the process is complete (indicated by rc = null), 1150 // get the process's completion info (RC and stopTimestamp) 1151 1152 Map processMap = (Map)res.resultObj; 1153 String processRCString = (String)processMap.get("rc"); 1154 1155 if (processRCString != null) 1156 { 1157 processRC = Long.parseLong(processRCString); 1158 stopTimestamp = (String)processMap.get("endTimestamp"); 1159 } 1160 else 1161 { 1162 // Process is not yet complete, so stop it 1163 1164 res = job.submitSync( 1165 location, "PROCESS", "STOP HANDLE " + processHandle); 1166 1167 if (debug) 1168 { 1169 STAX.logToJVMLog( 1170 "Debug", job.getJobNumber(), 1171 "STAXProcessActionFactory::handleStopRequest: " + 1172 "PROCESS STOP HANDLE " + processHandle + 1173 ", RC=" + res.rc); 1174 } 1175 1176 if (res.rc == STAFResult.Ok) 1177 { 1178 // Delay to allow the STAF/Process/End message (generated 1179 // by the PROCESS STOP HANDLE request) to be sent to the 1180 // STAX service machine and processed. 1181 1182 try 1183 { 1184 Thread.sleep(1000); // Sleep 1 second 1185 } 1186 catch (InterruptedException ex) 1187 { } 1188 1189 // Now check if the handle exists (just in case the 1190 // STAF/Process/End message was not successfully sent) 1191 1192 res = job.submitSync( 1193 location, "PROCESS", "QUERY HANDLE " + processHandle); 1194 1195 if (debug) 1196 { 1197 STAX.logToJVMLog( 1198 "Debug", job.getJobNumber(), 1199 "STAXProcessActionFactory::handleStopRequest: " + 1200 "PROCESS QUERY HANDLE " + processHandle + 1201 ", RC=" + res.rc); 1202 } 1203 1204 if (res.rc == STAFResult.Ok) 1205 { 1206 // Get the process's completion info (RC and 1207 // stopTimestamp) 1208 1209 processMap = (Map)res.resultObj; 1210 processRCString = (String)processMap.get("rc"); 1211 1212 if (processRCString != null) 1213 { 1214 processRC = Long.parseLong(processRCString); 1215 stopTimestamp = (String)processMap.get( 1216 "endTimestamp"); 1217 } 1218 } 1219 else if (res.rc == STAFResult.HandleDoesNotExist) 1220 { 1221 // The process handle no longer exists so the 1222 // STAF/Process/End message was successfully sent to 1223 // the STAX service machine and processed so we can 1224 // return. 1225 1226 return new STAFResult(STAFResult.Ok); 1227 } 1228 } 1229 } 1230 } 1231 1232 if (stopTimestamp.length() == 0) 1233 { 1234 // Assign the current timestamp as the time the process was stopped 1235 1236 stopTimestamp = (new STAXTimestamp()).getTimestampString(); 1237 } 1238 1239 // Assign an null fileList since no file data returned by the process 1240 // is available to us 1241 1242 List fileList = null; 1243 1244 // Note that if this process has an active process-action, stopping 1245 // the process does not "terminate" the process-action., 1246 1247 // Notify STAX that the process is complete 1248 1249 processAction.processComplete( 1250 location, processHandle, processRC, fileList, stopTimestamp); 1251 1252 return new STAFResult(STAFResult.Ok); 1253 } 1254 getHelpInfo(String lineSep)1255 public String getHelpInfo(String lineSep) 1256 { 1257 return "STOP JOB <Job ID> PROCESS <Location:Handle>"; 1258 } 1259 1260 private String fName; 1261 private STAFMapClassDefinition fProcessInfoMapClass; 1262 private STAFMapClassDefinition fQueryProcessMapClass; 1263 private STAFCommandParser fStopParser = new STAFCommandParser(); 1264 private STAFCommandParser fStopGenericParser = new STAFCommandParser(); 1265 1266 private static String fDTDInfo = 1267 "\n" + 1268 "<!--================= The STAF Process Element ===================== -->\n" + 1269 "<!--\n" + 1270 " Specifies a STAF process to be started.\n" + 1271 " All of its non-empty element values are evaluated via Python.\n" + 1272 "-->\n" + 1273 "<!ENTITY % procgroup1 '((parms?, workdir?) | (workdir?, parms?))'>\n" + 1274 "<!ENTITY % procgroup2 '((title?, workload?) | (workload?, title?))'>\n" + 1275 "<!ENTITY % procgroup1a '((parms?, workload?) | (workload?, parms?))'>\n" + 1276 "<!ENTITY % procgroup2a '((title?, workdir?) | (workdir?, title?))'>\n" + 1277 "<!ENTITY % procgroup3 '(((vars | var | envs | env)*, useprocessvars?) |\n" + 1278 " (useprocessvars?, (vars | var | envs | env)*))'>\n" + 1279 "<!ENTITY % procgroup4 '(((username, password?)?, disabledauth?) |\n" + 1280 " ((disabledauth?, (username, password?)?)))'>\n" + 1281 "<!ENTITY % procgroup5 '((stdin?, stdout?, stderr?) |\n" + 1282 " (stdout?, stderr?, stdin?) |\n" + 1283 " (stderr?, stdin?, stdout?) |\n" + 1284 " (stdin?, stderr?, stdout?) |\n" + 1285 " (stdout?, stdin?, stderr?) |\n" + 1286 " (stderr?, stdout?, stdin?))'>\n" + 1287 "<!ENTITY % returnfileinfo '(returnfiles | returnfile)*'>\n" + 1288 "<!ENTITY % procgroup5a '((%returnfileinfo;, returnstdout?, returnstderr?) |\n" + 1289 " (returnstdout?, returnstderr?, %returnfileinfo;) |\n" + 1290 " (returnstderr?, %returnfileinfo;, returnstdout?) |\n" + 1291 " (%returnfileinfo;, returnstderr?, returnstdout?) |\n" + 1292 " (returnstdout?, %returnfileinfo;, returnstderr?) |\n" + 1293 " (returnstderr?, returnstdout?, %returnfileinfo;))'>\n" + 1294 //"<!ENTITY % procgroup6 '((stopusing?, console?, statichandlename?) |\n" + 1295 //" (stopusing?, statichandlename?, console?) |\n" + 1296 //" (console?, stopusing?, statichandlename?) |\n" + 1297 //" (console?, statichandlename?, stopusing?) |\n" + 1298 //" (statichandlename?, stopusing?, console?) |\n" + 1299 //" (statichandlename?, console?, stopusing?))'>\n" + 1300 "<!ENTITY % procgroup6 '((stopusing?, console?, focus?, statichandlename?) |\n" + 1301 " (stopusing?, console?, statichandlename?, focus?) |\n" + 1302 " (stopusing?, focus?, console?, statichandlename?) |\n" + 1303 " (stopusing?, focus?, statichandlename?, console?) |\n" + 1304 " (stopusing?, statichandlename?, console?, focus?) |\n" + 1305 " (stopusing?, statichandlename?, focus?, console?) |\n" + 1306 " (console?, focus?, stopusing?, statichandlename?) |\n" + 1307 " (console?, focus?, statichandlename?, stopusing?) |\n" + 1308 " (console?, stopusing?, focus?, statichandlename?) |\n" + 1309 " (console?, stopusing?, statichandlename?, focus?) |\n" + 1310 " (console?, statichandlename?, focus?, stopusing?) |\n" + 1311 " (console?, statichandlename?, stopusing?, focus?) |\n" + 1312 " (focus?, console?, stopusing?, statichandlename?) |\n" + 1313 " (focus?, console?, statichandlename?, stopusing?) |\n" + 1314 " (focus?, stopusing?, console?, statichandlename?) |\n" + 1315 " (focus?, stopusing?, statichandlename?, console?) |\n" + 1316 " (focus?, statichandlename?, console?, stopusing?) |\n" + 1317 " (focus?, statichandlename?, stopusing?, console?) |\n" + 1318 " (statichandlename?, stopusing?, console?, focus?) |\n" + 1319 " (statichandlename?, stopusing?, focus?, console?) |\n" + 1320 " (statichandlename?, console?, focus?, stopusing?) |\n" + 1321 " (statichandlename?, console?, stopusing?, focus?) |\n" + 1322 " (statichandlename?, focus?, console?, stopusing?) |\n" + 1323 " (statichandlename?, focus?, stopusing?, console?))'>\n" + 1324 "<!ELEMENT process (location, command,\n" + 1325 " ((%procgroup1;, %procgroup2;) |\n" + 1326 " (%procgroup2;, %procgroup1;) |\n" + 1327 " (%procgroup1a;, %procgroup2a;) |\n" + 1328 " (%procgroup2a;, %procgroup1a;)),\n" + 1329 " %procgroup3;,\n" + 1330 " ((%procgroup4;, %procgroup5;, %procgroup5a;, %procgroup6;) |\n" + 1331 " (%procgroup4;, %procgroup6;, %procgroup5;, %procgroup5a;) |\n" + 1332 " (%procgroup5;, %procgroup5a;, %procgroup4;, %procgroup6;) |\n" + 1333 " (%procgroup5;, %procgroup5a;, %procgroup6;, %procgroup4;) |\n" + 1334 " (%procgroup6;, %procgroup4;, %procgroup5;, %procgroup5a;) |\n" + 1335 " (%procgroup6;, %procgroup5;, %procgroup5a;, %procgroup4;)),\n" + 1336 " other?, process-action?)>\n" + 1337 "<!ATTLIST process\n" + 1338 " name CDATA #IMPLIED\n" + 1339 ">\n" + 1340 "\n" + 1341 "<!--\n" + 1342 " The process element must contain a location element and a\n" + 1343 " command element.\n" + 1344 "-->\n" + 1345 "<!ELEMENT location (#PCDATA)>\n" + 1346 "<!ELEMENT command (#PCDATA)>\n" + 1347 "<!ATTLIST command\n" + 1348 " mode CDATA \"'default'\"\n" + 1349 " shell CDATA #IMPLIED\n" + 1350 ">\n" + 1351 "\n" + 1352 "<!--\n" + 1353 " The parms element specifies any parameters that you wish to\n" + 1354 " pass to the command.\n" + 1355 " The value is evaluated via Python to a string.\n" + 1356 "-->\n" + 1357 "<!ELEMENT parms (#PCDATA)>\n" + 1358 "<!ATTLIST parms\n" + 1359 " if CDATA \"1\"\n" + 1360 ">\n" + 1361 "\n" + 1362 "<!--\n" + 1363 " The workload element specifies the name of the workload for\n" + 1364 " which this process is a member. This may be useful in\n" + 1365 " conjunction with other process elements.\n" + 1366 " The value is evaluated via Python to a string.\n" + 1367 "-->\n" + 1368 "<!ELEMENT workload (#PCDATA)>\n" + 1369 "<!ATTLIST workload\n" + 1370 " if CDATA \"1\"\n" + 1371 ">\n" + 1372 "\n" + 1373 "<!--\n" + 1374 " The title element specifies the program title of the process.\n" + 1375 " Unless overridden by the process, the title will be the text\n" + 1376 " that is displayed on the title bar of the application.\n" + 1377 " The value is evaluated via Python to a string.\n" + 1378 "-->\n" + 1379 "<!ELEMENT title (#PCDATA)>\n" + 1380 "<!ATTLIST title\n" + 1381 " if CDATA \"1\"\n" + 1382 ">\n" + 1383 "\n" + 1384 "<!--\n" + 1385 " The workdir element specifies the directory from which the\n" + 1386 " command should be executed. If you do not specify this\n" + 1387 " element, the command will be started from whatever directory\n" + 1388 " STAFProc is currently in.\n" + 1389 " The value is evaluated via Python to a string.\n" + 1390 "-->\n" + 1391 "<!ELEMENT workdir (#PCDATA)>\n" + 1392 "<!ATTLIST workdir\n" + 1393 " if CDATA \"1\"\n" + 1394 ">\n" + 1395 "\n" + 1396 "<!--\n" + 1397 " The vars (and var) elements specify STAF variables that go into the\n" + 1398 " process specific STAF variable pool.\n" + 1399 " The value must evaluate via Python to a string or a list of \n" + 1400 " strings. Multiple vars elements may be specified for a process.\n" + 1401 " The format for each variable is:\n" + 1402 " 'varname=value'\n" + 1403 " So, a list containing 3 variables could look like:\n" + 1404 " ['var1=value1', 'var2=value2', 'var3=value3']\n" + 1405 " Specifying only one variable could look like either:\n" + 1406 " ['var1=value1'] or \n" + 1407 " 'var1=value1'\n" + 1408 "-->\n" + 1409 "<!ELEMENT vars (#PCDATA)>\n" + 1410 "<!ATTLIST vars\n" + 1411 " if CDATA \"1\"\n" + 1412 ">\n" + 1413 "\n" + 1414 "<!ELEMENT var (#PCDATA)>\n" + 1415 "<!ATTLIST var\n" + 1416 " if CDATA \"1\"\n" + 1417 ">\n" + 1418 "\n" + 1419 "<!--\n" + 1420 " The envs (and env) elements specify environment variables that will\n" + 1421 " be set for the process. Environment variables may be mixed case,\n" + 1422 " however most programs assume environment variable names will\n" + 1423 " be uppercase, so, in most cases, ensure that your environment\n" + 1424 " variable names are uppercase.\n" + 1425 " The value must evaluate via Python to a string or a list of \n" + 1426 " strings. Multiple envs elements may be specified for a process.\n" + 1427 " The format for each variable is:\n" + 1428 " 'varname=value'\n" + 1429 " So, a list containing 3 variables could look like:\n" + 1430 " ['ENV_VAR_1=value1', 'ENV_VAR_2=value2', 'ENV_VAR_3=value3']\n" + 1431 " Specifying only one variable could look like either:\n" + 1432 " ['ENV_VAR_1=value1'] or \n" + 1433 " 'ENV_VAR_1=value1'\n" + 1434 "-->\n" + 1435 "<!ELEMENT envs (#PCDATA)>\n" + 1436 "<!ATTLIST envs\n" + 1437 " if CDATA \"1\"\n" + 1438 ">\n" + 1439 "\n" + 1440 "<!ELEMENT env (#PCDATA)>\n" + 1441 "<!ATTLIST env\n" + 1442 " if CDATA \"1\"\n" + 1443 ">\n" + 1444 "<!--\n" + 1445 " The useprocessvars element specifies that STAF variable\n" + 1446 " references should try to be resolved from the STAF variable\n" + 1447 " pool associated with the process being started first.\n" + 1448 " If the STAF variable is not found in this pool, the STAF\n" + 1449 " global variable pool should then be searched.\n" + 1450 "-->\n" + 1451 "<!ELEMENT useprocessvars EMPTY>\n" + 1452 "<!ATTLIST useprocessvars\n" + 1453 " if CDATA \"1\"\n" + 1454 ">\n" + 1455 "\n" + 1456 "<!--\n" + 1457 " The stopusing element allows you to specify the method by\n" + 1458 " which this process will be STOPed, if not overridden on the\n" + 1459 " STOP command.\n" + 1460 " The value is evaluated via Python to a string.\n" + 1461 "-->\n" + 1462 "<!ELEMENT stopusing (#PCDATA)>\n" + 1463 "<!ATTLIST stopusing\n" + 1464 " if CDATA \"1\"\n" + 1465 ">\n" + 1466 "\n" + 1467 "<!--\n" + 1468 " The console element allows you to specify if the process should\n" + 1469 " get a new console window or share the STAFProc console.\n" + 1470 "\n" + 1471 " use Must evaluate via Python to a string containing either:\n" + 1472 " - 'new' specifies that the process should get a new console\n" + 1473 " window. This option only has effect on Windows systems.\n" + 1474 " This is the default for Windows systems.\n" + 1475 " - 'same' specifies that the process should share the\n" + 1476 " STAFProc console. This option only has effect on Windows\n" + 1477 " systems. This is the default for Unix systems.\n" + 1478 "-->\n" + 1479 "<!ELEMENT console EMPTY>\n" + 1480 "<!ATTLIST console\n" + 1481 " if CDATA \"1\"\n" + 1482 " use CDATA #REQUIRED\n" + 1483 ">\n" + 1484 "\n" + 1485 "<!--\n" + 1486 " The focus element allows you to specify the focus that is to be\n" + 1487 " given to any new windows opened when starting a process on a Windows\n" + 1488 " system. The window(s) it effects depends on whether you are using\n" + 1489 " the 'default' or the 'shell' command mode:\n" + 1490 " - Default command mode (no SHELL option): The focus specified is\n" + 1491 " given to any new windows opened by the command specified.\n" + 1492 " - Shell command mode: The focus specified is given only to the\n" + 1493 " new shell command window opened, not to any windows opened by\n" + 1494 " the specified command.\n" + 1495 "\n" + 1496 " The focus element only has effect on Windows systems and requires\n" + 1497 " STAF V3.1.4 or later on the machine where the process is run.\n" + 1498 "\n" + 1499 " mode Must evaluate via Python to a string containing one of the\n" + 1500 " following values:\n" + 1501 " - 'background' specifies to display a window in the background\n" + 1502 " (e.g. not give it focus) in its most recent size and position.\n" + 1503 " This is the default.\n" + 1504 " - 'foreground' specifies to display a window in the foreground\n" + 1505 " (e.g. give it focus) in its most recent size and position.\n" + 1506 " - 'minimized' specifies to display a window as minimized.\n" + 1507 "-->\n" + 1508 "<!ELEMENT focus EMPTY>\n" + 1509 "<!ATTLIST focus\n" + 1510 " if CDATA \"1\"\n" + 1511 " mode CDATA #REQUIRED\n" + 1512 ">\n" + 1513 "\n" + 1514 "<!--\n" + 1515 " The username element specifies the username under which \n" + 1516 " the process should be started.\n" + 1517 " The value is evaluated via Python to a string.\n" + 1518 "-->\n" + 1519 "<!ELEMENT username (#PCDATA)>\n" + 1520 "<!ATTLIST username\n" + 1521 " if CDATA \"1\"\n" + 1522 ">\n" + 1523 "\n" + 1524 "<!--\n" + 1525 " The password element specifies the password with which to\n" + 1526 " authenticate the user specified with the username element.\n" + 1527 " The value is evaluated via Python to a string.\n" + 1528 "-->\n" + 1529 "<!ELEMENT password (#PCDATA)>\n" + 1530 "<!ATTLIST password\n" + 1531 " if CDATA \"1\"\n" + 1532 ">\n" + 1533 "\n" + 1534 "<!-- The disabledauth element specifies the action to take if a\n" + 1535 " username/password is specified but authentication has been disabled.\n" + 1536 "\n" + 1537 " action Must evaluate via Python to a string containing either:\n" + 1538 " - 'error' specifies that an error should be returned.\n" + 1539 " - 'ignore' specifies that any username/password specified\n" + 1540 " is ignored if authentication is disabled.\n" + 1541 " This action overrides any default specified in the STAF\n" + 1542 " configuration file.\n" + 1543 "-->\n" + 1544 "<!ELEMENT disabledauth EMPTY>\n" + 1545 "<!ATTLIST disabledauth\n" + 1546 " if CDATA \"1\"\n" + 1547 " action CDATA #REQUIRED\n" + 1548 ">\n" + 1549 "\n" + 1550 "<!--\n" + 1551 " Specifies that a static handle should be created for this process.\n" + 1552 " The value is evaluated via Python to a string. It will be the\n" + 1553 " registered name of the static handle. Using this option will also\n" + 1554 " cause the environment variable STAF_STATIC_HANDLE to be set\n" + 1555 " appropriately for the process.\n" + 1556 "-->\n" + 1557 "<!ELEMENT statichandlename (#PCDATA)>\n" + 1558 "<!ATTLIST statichandlename\n" + 1559 " if CDATA \"1\"\n" + 1560 ">\n" + 1561 "\n" + 1562 "<!--\n" + 1563 " The stdin element specifies the name of the file from which\n" + 1564 " standard input will be read. The value is evaluated via\n" + 1565 " Python to a string.\n" + 1566 "-->\n" + 1567 "<!ELEMENT stdin (#PCDATA)>\n" + 1568 "<!ATTLIST stdin\n" + 1569 " if CDATA \"1\"\n" + 1570 ">\n" + 1571 "\n" + 1572 "<!--\n" + 1573 " The stdout element specifies the name of the file to which\n" + 1574 " standard output will be redirected.\n" + 1575 " The mode and filename are evaluated via Python to a string.\n" + 1576 "-->\n" + 1577 "<!ELEMENT stdout (#PCDATA)>\n" + 1578 "<!-- mode specifies what to do if the file already exists.\n" + 1579 " The value must evaluate via Python to one of the\n" + 1580 " following:\n" + 1581 " 'replace' - specifies that the file will be replaced.\n" + 1582 " 'append' - specifies that the process' standard\n" + 1583 " output will be appended to the file.\n" + 1584 "-->\n" + 1585 "<!ATTLIST stdout\n" + 1586 " if CDATA \"1\"\n" + 1587 " mode CDATA \"'replace'\"\n" + 1588 ">\n" + 1589 "\n" + 1590 "<!--\n" + 1591 " The stderr element specifies the file to which standard error will\n" + 1592 " be redirected. The mode and filename are evaluated via Python to a\n" + 1593 " string.\n" + 1594 "-->\n" + 1595 "<!ELEMENT stderr (#PCDATA)>\n" + 1596 "<!-- mode specifies what to do if the file already exists or to\n" + 1597 " redirect standard error to the same file as standard output.\n" + 1598 " The value must evaluate via Python to one of the following:\n" + 1599 " 'replace' - specifies that the file will be replaced.\n" + 1600 " 'append' - specifies that the process's standard error will\n" + 1601 " be appended to the file.\n" + 1602 " 'stdout' - specifies to redirect standard error to the\n" + 1603 " same file to which standard output is redirected.\n" + 1604 " If a file name is specified, it is ignored.\n" + 1605 "-->\n" + 1606 "<!ATTLIST stderr\n" + 1607 " if CDATA \"1\"\n" + 1608 " mode CDATA \"'replace'\"\n" + 1609 ">\n" + 1610 "\n" + 1611 "<!--\n" + 1612 " The returnstdout element specifies to return in STAXResult\n" + 1613 " the contents of the file where standard output was redirected\n" + 1614 " when the process completes.\n" + 1615 "-->\n" + 1616 "<!ELEMENT returnstdout EMPTY>\n" + 1617 "<!ATTLIST returnstdout\n" + 1618 " if CDATA \"1\"\n" + 1619 ">\n" + 1620 "\n" + 1621 "<!--\n" + 1622 " The returnstderr element specifies to return in STAXResult\n" + 1623 " the contents of the file where standard error was redirected\n" + 1624 " when the process completes.\n" + 1625 "-->\n" + 1626 "<!ELEMENT returnstderr EMPTY>\n" + 1627 "<!ATTLIST returnstderr\n" + 1628 " if CDATA \"1\"\n" + 1629 ">\n" + 1630 "\n" + 1631 "<!--\n" + 1632 " The returnfiles (and returnfile) elements specify that the\n" + 1633 " contents of the specified file(s) should be returned in\n" + 1634 " STAXResult when the process completes. The value must evaluate\n" + 1635 " via Python to a string or a list of strings. Multiple returnfile(s)\n" + 1636 " elements may be specified for a process.\n" + 1637 "-->\n" + 1638 "<!ELEMENT returnfiles (#PCDATA)>\n" + 1639 "<!ATTLIST returnfiles\n" + 1640 " if CDATA \"1\"\n" + 1641 ">\n" + 1642 "\n" + 1643 "<!ELEMENT returnfile (#PCDATA)>\n" + 1644 "<!ATTLIST returnfile\n" + 1645 " if CDATA \"1\"\n" + 1646 ">\n" + 1647 "\n" + 1648 "<!--\n" + 1649 " The process-action element specifies a task to be executed\n" + 1650 " when a process has started.\n" + 1651 "-->\n" + 1652 "<!ELEMENT process-action (%task;)>\n" + 1653 "<!ATTLIST process-action\n" + 1654 " if CDATA \"1\"\n" + 1655 ">\n" + 1656 "<!--\n" + 1657 " The other element specifies any other STAF parameters that\n" + 1658 " may arise in the future. It is used to pass additional data\n" + 1659 " to the STAF PROCESS START request.\n" + 1660 " The value is evaluated via Python to a string.\n" + 1661 "-->\n" + 1662 "<!ELEMENT other (#PCDATA)>\n" + 1663 "<!ATTLIST other\n" + 1664 " if CDATA \"1\"\n" + 1665 ">\n"; 1666 1667 } // end Class 1668