KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jbatchengine > batch > BatchEngine


1 /*
2  jBatchEngine - jbatchengine.sourceforge.net
3  Copyright (C) 2006 by Simon Martinelli, Gampelen, Switzerland
4
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */

19 package net.sf.jbatchengine.batch;
20
21 import java.io.IOException JavaDoc;
22 import java.io.PrintWriter JavaDoc;
23 import java.io.StringWriter JavaDoc;
24 import java.net.InetAddress JavaDoc;
25 import java.util.Date JavaDoc;
26 import java.util.Properties JavaDoc;
27
28 import net.sf.jbatchengine.batch.adapter.Adapter;
29 import net.sf.jbatchengine.batch.util.CommandFileParser;
30 import net.sf.jbatchengine.batch.util.LogRedirectionThread;
31 import net.sf.jbatchengine.model.Job;
32
33 import org.apache.commons.cli.CommandLine;
34 import org.apache.commons.cli.CommandLineParser;
35 import org.apache.commons.cli.HelpFormatter;
36 import org.apache.commons.cli.Option;
37 import org.apache.commons.cli.Options;
38 import org.apache.commons.cli.ParseException;
39 import org.apache.commons.cli.PosixParser;
40 import org.apache.log4j.Logger;
41 import org.springframework.context.ApplicationContext;
42 import org.springframework.context.support.ClassPathXmlApplicationContext;
43 import org.springframework.util.Log4jConfigurer;
44
45 /**
46  * BatchEngine.
47  *
48  * @author $Author: simas_ch $
49  * @version $Revision: 1.28 $, $Date: 2006/12/18 19:55:10 $
50  */

51 public class BatchEngine extends Thread JavaDoc {
52
53   /** The log. */
54   private static transient Logger log = Logger.getLogger(BatchEngine.class);
55
56   /** The should not redirect. */
57   private static boolean shouldNotRedirect;
58
59   /** The prop. */
60   private static Properties JavaDoc prop;
61
62   /** The adapter. */
63   private Adapter adapter;
64
65   /** The process. */
66   private Process JavaDoc process;
67
68   /** The Constant EXIT_VALUE_DEFAULT. */
69   private static final int EXIT_VALUE_DEFAULT = Integer.MIN_VALUE;
70
71   /**
72    * Constructs a BatchEngine.
73    */

74   private BatchEngine() {
75     String JavaDoc[] paths = { "applicationContext.xml" };
76
77     ApplicationContext ap = new ClassPathXmlApplicationContext(paths);
78
79     adapter = (Adapter) ap.getBean("adapter");
80
81     // 4. Shutdownhook initialiseren
82
Runtime.getRuntime().addShutdownHook(new Thread JavaDoc() {
83
84       public void run() {
85         terminate();
86       }
87     });
88   }
89
90   /**
91    * The Main method of BatchEngine.
92    *
93    * @param args the args
94    * @throws Exception the exception
95    */

96   public static void main(String JavaDoc[] args) throws Exception JavaDoc {
97     init(args);
98   }
99
100   /*
101    * (non-Javadoc)
102    *
103    * @see java.lang.Thread#run()
104    */

105   /**
106    * Run.
107    */

108   public void run() {
109
110     while (true) {
111       try {
112         // read next job to process
113
log.info("Get next Job to process");
114
115         Job job = this.adapter.getNextJob(0);
116         // get batch command
117
String JavaDoc batch = prop.getProperty(job.getTyp());
118
119         if (batch == null) {
120           log.fatal("Batchtyp not configured");
121           throw new RuntimeException JavaDoc("BatchTyp not configured");
122         }
123
124         // if it is a .jcmd file assume that it is a java programm and parse the file
125
if (batch.indexOf(".jcmd") > -1) {
126           batch = CommandFileParser.parse(batch);
127         }
128
129         // add optional paramters
130
if (job.getParameters() != null && !job.getParameters().equals("")) {
131           batch += " " + job.getParameters();
132         }
133
134         // execute the process
135
log.info("Executing Job: " + batch);
136         process = Runtime.getRuntime().exec(batch);
137
138         job.setStatus(Job.STATUS_RUNNING);
139         job.setStarted_at(new Date JavaDoc());
140         job.setQueue(InetAddress.getLocalHost().getHostName());
141         adapter.updateJob(job);
142
143         if (!shouldNotRedirect) {
144           // redirect STDOUT and STDERR
145
new LogRedirectionThread(process, LogRedirectionThread.OUT).start();
146           new LogRedirectionThread(process, LogRedirectionThread.ERR).start();
147         }
148
149         int exitValue = EXIT_VALUE_DEFAULT;
150         long startMillis = System.currentTimeMillis();
151
152         while (true) {
153           // do forever
154
try {
155             Thread.sleep(10000);
156             exitValue = process.exitValue();
157           }
158           catch (IllegalThreadStateException JavaDoc e) {
159             // Ignore
160
}
161           catch (InterruptedException JavaDoc ie) {
162             // Ignore
163
}
164           // has exitValue changed?
165
if (exitValue != EXIT_VALUE_DEFAULT) {
166             break;
167           }
168           String JavaDoc timeoutString = prop.getProperty("timeout", "180000");
169           long timeout = Long.parseLong(timeoutString);
170           if ((System.currentTimeMillis() - startMillis) > timeout) {
171             // timeout reached
172
process.destroy();
173             job.setStatus(Job.STATUS_FINISHED_WITH_TIMEOUT);
174             job.setEnded_at(new Date JavaDoc());
175             job.setReturncode("" + exitValue);
176             adapter.updateJob(job);
177             exitValue = EXIT_VALUE_DEFAULT;
178             break;
179           }
180           job = adapter.getJob(job.getId());
181           if (job.getStatus().equals(Job.STATUS_WAITING_FOR_CANCEL)) {
182             // job is to cancel
183
process.destroy();
184             job.setStatus(Job.STATUS_CANCELED);
185             job.setEnded_at(new Date JavaDoc());
186             job.setReturncode("" + exitValue);
187             adapter.updateJob(job);
188             exitValue = EXIT_VALUE_DEFAULT;
189             break;
190           }
191         }
192
193         // job finished set status
194
if (exitValue == 0) {
195           // status has not modifed bevor
196
log.info("Job finished without errors");
197           job.setEnded_at(new Date JavaDoc());
198           job.setStatus(Job.STATUS_FINISHED);
199           job.setReturncode("" + exitValue);
200           adapter.updateJob(job);
201         }
202         else if (exitValue == EXIT_VALUE_DEFAULT) {
203           // do nothing! exitvalue was changed before
204
}
205         else {
206           log.info("Job terminated error code: " + exitValue);
207           job.setEnded_at(new Date JavaDoc());
208           job.setStatus(Job.STATUS_FINISHED_WITH_ERRORS);
209           job.setReturncode("" + exitValue);
210           adapter.updateJob(job);
211         }
212         process = null;
213       }
214       catch (Exception JavaDoc e) {
215         log.fatal(e);
216       }
217     }
218   }
219
220   /**
221    * Initializes the BatchEngine and constructs and starts BatchEngine Threads.
222    *
223    * @param args the args
224    * @throws IOException the IO exception
225    * @throws ParseException the parse exception
226    * @throws InterruptedException
227    */

228   private static void init(String JavaDoc[] args) throws ParseException, IOException JavaDoc, InterruptedException JavaDoc {
229
230     Log4jConfigurer.initLogging("classpath:log4j.xml");
231
232     log.info("BatchEngine initalize started");
233
234     CommandLine cl = parseCommandLineArgs(args);
235     if (cl != null) {
236       shouldNotRedirect = cl.hasOption('n');
237     }
238
239     prop = new Properties JavaDoc();
240     prop.load(ClassLoader.getSystemResourceAsStream("jbatchengine.properties"));
241
242     int numberOfThreads = Integer.parseInt(prop.getProperty("numberOfThreads", "1"));
243
244     for (int i = 0; i < numberOfThreads; i++) {
245       BatchEngine batchEngine = new BatchEngine();
246       log.info("BatchEngine starting thread.");
247       batchEngine.start();
248       Thread.sleep(5000);
249     }
250
251     log.info("BatchEngine initalize ended");
252   }
253
254   /**
255    * Parses the commandline.
256    *
257    * @param args the args
258    * @return a CommandLine
259    * @throws ParseException the parse exception
260    */

261   private static CommandLine parseCommandLineArgs(String JavaDoc[] args) throws ParseException {
262
263     Options options = new Options();
264     Option op1 = new Option("n", "noredirect", true,
265         "no redirection of the system out and the system err from the child processes to this process");
266     op1.setRequired(false);
267     op1.setArgName("switch");
268     op1.setOptionalArg(true);
269     options.addOption(op1);
270
271     Option op2 = new Option("c", "check", true, "check");
272     op2.setRequired(false);
273     op2.setArgName("switch");
274     op2.setOptionalArg(true);
275     options.addOption(op2);
276
277     if ((args != null) && (args.length != 0)) {
278       CommandLineParser parser = new PosixParser();
279       try {
280         return parser.parse(options, args);
281       }
282       catch (ParseException e) {
283         logUsage(options);
284         throw e;
285       }
286     }
287     return null;
288   }
289
290   /**
291    * If the parameters are not correctly set it displays informations about the options to set.
292    *
293    * @param options the options
294    */

295   private static void logUsage(Options options) {
296     HelpFormatter formatter = new HelpFormatter();
297     StringWriter JavaDoc sw = new StringWriter JavaDoc();
298     formatter.printHelp(new PrintWriter JavaDoc(sw), 100, "<commandfile_name>", "", options, 20, 10, "");
299     sw.flush();
300     log.fatal("\n" + sw);
301   }
302
303   /**
304    * Shutdown hook to stop the child processes.
305    */

306   private void terminate() {
307     log.info("BatchEngine about to stop");
308
309     if (process != null) {
310       process.destroy();
311       log.info("Child process forced to stop");
312     }
313     log.info("BatchEngine stopped");
314   }
315 }
Popular Tags