Java tutorial
/* * Copyright 2001-2009 James House * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * */ /* * Previously Copyright (c) 2001-2004 James House */ package org.quartz.jobs; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /* * <p> Built in job for executing native executables in a separate process.</p> * * If PROP_WAIT_FOR_PROCESS is true, then the Integer exit value of the process * will be saved as the job execution result in the JobExecutionContext. * * @see #PROP_COMMAND * @see #PROP_PARAMETERS * @see #PROP_WAIT_FOR_PROCESS * @see #PROP_CONSUME_STREAMS * * @author Matthew Payne * @author James House * @author Steinar Overbeck Cook * @date Sep 17, 2003 @Time: 11:27:13 AM */ public class NativeJob implements Job { private final Log log = LogFactory.getLog(getClass()); /* *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constants. * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** * Required parameter that specifies the name of the command (executable) * to be ran. */ public static final String PROP_COMMAND = "command"; /** * Optional parameter that specifies the parameters to be passed to the * executed command. */ public static final String PROP_PARAMETERS = "parameters"; /** * Optional parameter (value should be 'true' or 'false') that specifies * whether the job should wait for the execution of the native process to * complete before it completes. * * <p>Defaults to <code>true</code>.</p> */ public static final String PROP_WAIT_FOR_PROCESS = "waitForProcess"; /** * Optional parameter (value should be 'true' or 'false') that specifies * whether the spawned process's stdout and stderr streams should be * consumed. If the process creates output, it is possible that it might * 'hang' if the streams are not consumed. * * <p>Defaults to <code>false</code>.</p> */ public static final String PROP_CONSUME_STREAMS = "consumeStreams"; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap data = context.getMergedJobDataMap(); String command = data.getString(PROP_COMMAND); String parameters = data.getString(PROP_PARAMETERS); if (parameters == null) { parameters = ""; } boolean wait = true; if (data.containsKey(PROP_WAIT_FOR_PROCESS)) { wait = data.getBooleanValue(PROP_WAIT_FOR_PROCESS); } boolean consumeStreams = false; if (data.containsKey(PROP_CONSUME_STREAMS)) { consumeStreams = data.getBooleanValue(PROP_CONSUME_STREAMS); } Integer exitCode = this.runNativeCommand(command, parameters, wait, consumeStreams); context.setResult(exitCode); } protected Log getLog() { return log; } private Integer runNativeCommand(String command, String parameters, boolean wait, boolean consumeStreams) throws JobExecutionException { String[] cmd = null; String[] args = new String[2]; Integer result = null; args[0] = command; args[1] = parameters; try { //with this variable will be done the swithcing String osName = System.getProperty("os.name"); // specific for Windows if (osName.startsWith("Windows")) { cmd = new String[args.length + 2]; if (osName.equals("Windows 95")) { // windows 95 only cmd[0] = "command.com"; } else { cmd[0] = "cmd.exe"; } cmd[1] = "/C"; for (int i = 0; i < args.length; i++) { cmd[i + 2] = args[i]; } } else if (osName.equals("Linux")) { if (cmd == null) { cmd = new String[3]; } cmd[0] = "/bin/sh"; cmd[1] = "-c"; cmd[2] = args[0] + " " + args[1]; } else { // try this... cmd = args; } Runtime rt = Runtime.getRuntime(); // Executes the command getLog().info("About to run " + cmd[0] + " " + cmd[1] + " " + (cmd.length > 2 ? cmd[2] : "") + " ..."); Process proc = rt.exec(cmd); // Consumes the stdout from the process StreamConsumer stdoutConsumer = new StreamConsumer(proc.getInputStream(), "stdout"); // Consumes the stderr from the process if (consumeStreams) { StreamConsumer stderrConsumer = new StreamConsumer(proc.getErrorStream(), "stderr"); stdoutConsumer.start(); stderrConsumer.start(); } if (wait) { result = new Integer(proc.waitFor()); } // any error message? } catch (Exception x) { throw new JobExecutionException("Error launching native command: ", x, false); } return result; } /** * Consumes data from the given input stream until EOF and prints the data to stdout * * @author cooste * @author jhouse */ class StreamConsumer extends Thread { InputStream is; String type; /** * */ public StreamConsumer(InputStream inputStream, String type) { this.is = inputStream; this.type = type; } /** * Runs this object as a separate thread, printing the contents of the InputStream * supplied during instantiation, to either stdout or stderr */ public void run() { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(is)); String line = null; while ((line = br.readLine()) != null) { if (type.equalsIgnoreCase("stderr")) { getLog().warn(type + ">" + line); } else { getLog().info(type + ">" + line); } } } catch (IOException ioe) { getLog().error("Error consuming " + type + " stream of spawned process.", ioe); } finally { if (br != null) { try { br.close(); } catch (Exception ignore) { } } } } } }