reintroduced StringUtil.regexpReplace
[mir.git] / source / mir / producer / ExecuteProgramProducerNode.java
1 /*
2  * Copyright (C) 2001-2006 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License,
22  * and distribute linked combinations including the two.  You must obey the
23  * GNU General Public License in all respects for all of the code used other than
24  * the above mentioned libraries.  If you modify this file, you may extend this
25  * exception to your version of the file, but you are not obligated to do so.
26  * If you do not wish to do so, delete this exception statement from your version.
27  */
28 package mir.producer;
29
30 import mir.log.LoggerWrapper;
31 import mir.util.ParameterExpander;
32
33 import java.util.Map;
34
35 public class ExecuteProgramProducerNode extends AbstractProducerNode  {
36   private String scriptExpression;
37   private String maxDurationExpression;
38   private String outputVariableExpression;
39   private String returnValueVariableExpression;
40
41   public ExecuteProgramProducerNode(String aScriptExpression, String aMaxDurationExpression, String anOutputVariableExpression,
42                                     String aReturnValueVariableExpression) {
43     scriptExpression = aScriptExpression;
44     maxDurationExpression = aMaxDurationExpression;
45     outputVariableExpression = anOutputVariableExpression;
46     returnValueVariableExpression = aReturnValueVariableExpression;
47   }
48
49   public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure {
50     String script;
51     long maxDuration;
52
53     try {
54       script = ParameterExpander.expandExpression(aValueMap, scriptExpression);
55       maxDuration = ParameterExpander.evaluateIntegerExpressionWithDefault(aValueMap, maxDurationExpression, 0);
56
57       ProcessRunner runner = new ProcessRunner(aLogger, script);
58       runner.start();
59
60       synchronized (runner) {
61         runner.wait(maxDuration);
62       }
63       runner.interrupt();
64
65       if (runner.getFinished()) {
66         aLogger.info(script + " terminated successfully, return value = " + runner.getReturnValue() + ".");
67
68         if (returnValueVariableExpression != null) {
69           ParameterExpander.setValueForKey(aValueMap,
70               ParameterExpander.expandExpression(aValueMap, returnValueVariableExpression),
71               new Integer(runner.getReturnValue()));
72         }
73
74       }
75       else {
76         aLogger.info(script + " interrupted prematurely after " + maxDuration + "ms.");
77       }
78     }
79     catch (Throwable e) {
80       aLogger.error("Error while executing " + scriptExpression + " : " + e.toString());
81     }
82   }
83
84   private static class ProcessRunner extends Thread {
85     private String script;
86     private boolean finished = false;
87     private int returnValue = 0;
88     private LoggerWrapper logger;
89
90     public ProcessRunner(LoggerWrapper aLogger, String aScript) {
91       script = aScript;
92       logger = aLogger;
93     }
94
95     public boolean getFinished() {
96       return finished;
97     }
98
99     public int getReturnValue() {
100       return returnValue;
101     }
102
103     public void run() {
104       Process process = null;
105       try {
106         process = Runtime.getRuntime().exec(script);
107         returnValue = process.waitFor();
108
109         finished = true;
110
111         synchronized (this) {
112           this.notify();
113         }
114       }
115       catch (InterruptedException e) {
116         if (process!=null) {
117           process.destroy();
118         }
119       }
120       catch (Exception e) {
121         logger.error(script + " failed to execute: " + e.getMessage());
122       }
123     }
124   }
125
126 }