001/* 002 * Copyright (c) 2004-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.cipres.kepler; 031 032import java.util.Observable; 033import java.util.Observer; 034 035import javax.swing.JOptionPane; 036 037import org.cipres.helpers.JRun; 038 039import ptolemy.actor.CompositeActor; 040import ptolemy.actor.Manager; 041import ptolemy.actor.TypedAtomicActor; 042import ptolemy.actor.TypedIOPort; 043import ptolemy.data.IntToken; 044import ptolemy.data.StringToken; 045import ptolemy.data.expr.FileParameter; 046import ptolemy.data.expr.Parameter; 047import ptolemy.data.type.BaseType; 048import ptolemy.kernel.CompositeEntity; 049import ptolemy.kernel.util.IllegalActionException; 050import ptolemy.kernel.util.NameDuplicationException; 051import ptolemy.kernel.util.Nameable; 052 053////////////////////////////////////////////////////////////////////////// 054//// JRunCIPRes 055/** 056 * This actor calls the external applications. 057 * 058 * The JRunCIPRes actor provides a template to invoke external Cipres 059 * applications. A set of parameters is configured in the actor to collect 060 * application related information. The value of these parameters will be fed to 061 * the JRun object when the actor fires. Thus the GUIRun object will invoke the 062 * corresponding application with those values, like the input/output file names 063 * and the working directory. After the execution, if the external program 064 * returns correctly, the standard output of the execution will be sent to the 065 * standard output file, and the standard error will be sent to the standard 066 * error file. 067 * 068 * The user can also set some words to be monitored in the standard output 069 * stream. The observer/observable design pattern is used here. The JRunCIPRes 070 * object is an observer. The JRun object is an observable. Whenever the JRun 071 * object find any of these monitored words in the standard output steam of the 072 * program execution, it will notify the JRunCIPRes objects to promote the user 073 * handling the issue. Usually the JRunCIPRes actor will stop the execution of 074 * the program. 075 * 076 * @author Zhijie Guan 077 * @version $Id: JRunCIPRes.java 24234 2010-05-06 05:21:26Z welker $ 078 */ 079 080public class JRunCIPRes extends TypedAtomicActor implements Observer { 081 082 /** 083 * Construct JRunCIPRes source with the given container and name. 084 * 085 * @param container 086 * The container. 087 * @param name 088 * The name of this actor. 089 * @exception IllegalActionException 090 * If the entity cannot be contained by the proposed 091 * container. 092 * @exception NameDuplicationException 093 * If the container already has an actor with this name. 094 */ 095 096 public JRunCIPRes(CompositeEntity container, String name) 097 throws NameDuplicationException, IllegalActionException { 098 super(container, name); 099 100 // initialize the standard output port 101 standardOutput = new TypedIOPort(this, "standardOutput", false, true); 102 standardOutput.setDisplayName("Standard Output"); 103 standardOutput.setTypeEquals(BaseType.STRING); 104 105 // initialize the standard error port 106 standardError = new TypedIOPort(this, "standardError", false, true); 107 standardError.setDisplayName("Standard Error"); 108 standardError.setTypeEquals(BaseType.STRING); 109 110 // initialize the exit code port 111 exitCode = new TypedIOPort(this, "exitCode", false, true); 112 exitCode.setDisplayName("Exit Code"); 113 exitCode.setTypeEquals(BaseType.STRING); 114 115 // initialize the input trigger port 116 inputTrigger = new TypedIOPort(this, "inputTrigger", true, false); 117 inputTrigger.setDisplayName("Input Trigger"); 118 inputTrigger.setTypeEquals(BaseType.STRING); 119 120 // command name 121 command = new FileParameter(this, "command"); 122 command.setDisplayName("External Command"); 123 124 // standard output file name 125 outputFile = new FileParameter(this, "outputFile"); 126 outputFile.setDisplayName("Standard Output File"); 127 128 // standard error file name 129 errorFile = new FileParameter(this, "errorFile"); 130 errorFile.setDisplayName("Standard Error File"); 131 132 // arguments 133 arguments = new Parameter(this, "arguments", new StringToken("")); 134 arguments.setDisplayName("Arguments"); 135 136 // working directory 137 workingDirectory = new Parameter(this, "workingDirectory", 138 new StringToken("")); 139 workingDirectory.setDisplayName("Working Direcotry"); 140 141 // monitored error words 142 monitoredErrorWords = new Parameter(this, "monitoredErrorWords", 143 new StringToken("")); 144 monitoredErrorWords.setDisplayName("Error Words to be Monitored"); 145 146 _attachText("_iconDescription", "<svg>\n" + "<rect x=\"0\" y=\"0\" " 147 + "width=\"60\" height=\"20\" " + "style=\"fill:white\"/>\n" 148 + "</svg>\n"); 149 150 } 151 152 // ///////////////////////////////////////////////////////////////// 153 // // ports and parameters //// 154 155 /** 156 * The command path and name are defined in this parameter. 157 */ 158 public FileParameter command; 159 160 /** 161 * The standard output file's path and name are defined in this parameter. 162 */ 163 public FileParameter outputFile; 164 165 /** 166 * The standard error file's path and name are defined in this parameter. 167 */ 168 public FileParameter errorFile; 169 170 /** 171 * The arguments of the program that will be executed are defined in this 172 * parameter. 173 */ 174 public Parameter arguments; 175 176 /** 177 * The workfing directory of the external program is defined in this 178 * parameter. 179 */ 180 public Parameter workingDirectory; 181 182 /** 183 * The monitored words are defined in this parameter. 184 */ 185 public Parameter monitoredErrorWords; 186 187 /** 188 * The standard output stream of the execution is sent out through this 189 * port. 190 */ 191 public TypedIOPort standardOutput = null; 192 193 /** 194 * The standard error stream of the execution is sent out through this port. 195 */ 196 public TypedIOPort standardError = null; 197 198 /** 199 * The exit code of the execution is sent out through this port. 200 */ 201 public TypedIOPort exitCode = null; 202 203 /** 204 * The trigger that will enable the execution of this actor is received 205 * through this port. 206 */ 207 public TypedIOPort inputTrigger = null; 208 209 // ///////////////////////////////////////////////////////////////// 210 // // functional variables //// 211 212 // ///////////////////////////////////////////////////////////////// 213 // // public methods //// 214 215 /** 216 * Invoke the external program. The monitored words are being monitored 217 * during the execution. 218 * 219 * @exception IllegalActionException 220 * If it is thrown by the send() method sending out the 221 * token. 222 */ 223 public void fire() throws IllegalActionException { 224 if (inputTrigger.hasToken(0)) { 225 super.fire(); 226 try { 227 // get command file name 228 String commandFileName = ((StringToken) command.getToken()) 229 .stringValue(); 230 if (commandFileName.length() != 0) { 231 _jrun.setCommand(commandFileName); 232 } else { 233 System.out.println("Command is not defined!"); 234 throw new IllegalActionException("Command is not defined"); 235 } 236 237 // get standard output file name 238 String outFileName = ((StringToken) outputFile.getToken()) 239 .stringValue(); 240 if (outFileName.length() != 0) { 241 _jrun.setOutputFileName(outFileName); 242 } 243 244 // get standard error file name 245 String errorFileName = ((StringToken) errorFile.getToken()) 246 .stringValue(); 247 if (errorFileName.length() != 0) { 248 _jrun.setErrorFileName(errorFileName); 249 } 250 251 // get arguments string 252 String argumentsString = ((StringToken) arguments.getToken()) 253 .stringValue(); 254 if (argumentsString.length() != 0) { 255 _jrun.setArguments(argumentsString); 256 } 257 258 // get working directory 259 String workingDirName = ((StringToken) workingDirectory 260 .getToken()).stringValue(); 261 if (workingDirName.length() != 0) { 262 _jrun.setWorkingDirectory(workingDirName); 263 } 264 265 // Here we assume all the programs executed by JRunCIPRes must 266 // be finished to get the final results 267 // So the JRun is set to wait until the execution is finished 268 _jrun.setWaitForExecution(true); 269 270 // check if the user set the monitored error words 271 String errorWords = ((StringToken) monitoredErrorWords 272 .getToken()).stringValue(); 273 if (errorWords.length() != 0) { 274 _jrun.setMonitoredErrorWords(errorWords); 275 _jrun.addObserver(this); // add this GUIRunCIPRes as an 276 // observer 277 } 278 279 _jrun.execute(); // invoke the external program 280 281 exitCode.send(0, new IntToken(_jrun.getExitCode())); // send out 282 // the 283 // exit 284 // code 285 // token 286 287 if (_jrun.getExitCode() != 0) { 288 _terminateWorkflow = true; // set the flag to terminate the 289 // workflow since errors are 290 // reported 291 } else { 292 standardOutput.send(0, new StringToken(_jrun 293 .getStandardOutput())); 294 standardError.send(0, new StringToken(_jrun 295 .getStandardError())); 296 297 } 298 } catch (Exception e) { 299 e.printStackTrace(); 300 } 301 } 302 } 303 304 /** 305 * Observer function update jRunObj is the jRun object that runs the program 306 * obj is the String message that jRun object send back. This string message 307 * is the standard output/error line that contains the monitored words 308 */ 309 public void update(Observable jRunObj, Object obj) { 310 String outputMessage = (String) obj; 311 int stop = 0; // For default, we assume the execution should be stopped 312 // if any error appears 313 314 try { 315 // ask the user if we should abort the program execution 316 stop = JOptionPane.showConfirmDialog(null, // parent component 317 "The program execution reported the following error message.\n" 318 + // Message 319 "Would you like to stop the execution?\n" + // Message 320 outputMessage + "\n", // Error message for Standard 321 // output/error 322 "Error Reported", // Title 323 JOptionPane.YES_NO_OPTION, // Option type 324 JOptionPane.ERROR_MESSAGE); // Message type 325 } catch (Exception e) { 326 e.printStackTrace(); 327 } 328 329 if (stop == JOptionPane.YES_OPTION) { 330 ((JRun) jRunObj).stopExecution(); // stop the execution 331 } 332 333 } 334 335 /** 336 * Post fire the actor. Return false to indicated that the process has 337 * finished. If it returns true, the process will continue indefinitely. 338 */ 339 public boolean postfire() throws IllegalActionException { 340 if (_terminateWorkflow) { 341 Nameable container = getContainer(); 342 if (container instanceof CompositeActor) { 343 Manager manager = ((CompositeActor) container).getManager(); 344 if (manager != null) { 345 manager.finish(); // stop the workflow 346 } else { 347 throw new IllegalActionException(this, 348 "Cannot terminate the workflow without a Manager"); 349 } 350 } else { 351 throw new IllegalActionException(this, 352 "Cannot terminate the workflow without a container that is a CompositeActor"); 353 } 354 } 355 return !_terminateWorkflow; 356 } 357 358 // ///////////////////////////////////////////////////////////////// 359 // // private variables //// 360 /** 361 * JRun object to invoke external programs 362 */ 363 private JRun _jrun = new JRun(); 364 365 /** 366 * a flag to terminate the whole workflow since the execution of program got 367 * error messages 368 */ 369 private boolean _terminateWorkflow = false; 370}