org.quartz.jobs.NativeJob Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.servicemix.bundles.quartz
Show all versions of org.apache.servicemix.bundles.quartz
This OSGi bundle wraps quartz, quartz-jobs ${pkgVersion} jar file.
/*
* All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.
*
* 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.
*
*/
package org.quartz.jobs;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* Built in job for executing native executables in a separate process.
*
*
* JobDetail job = new JobDetail("dumbJob", null, org.quartz.jobs.NativeJob.class);
* job.getJobDataMap().put(org.quartz.jobs.NativeJob.PROP_COMMAND, "echo \"hi\" >> foobar.txt");
* Trigger trigger = TriggerUtils.makeSecondlyTrigger(5);
* trigger.setName("dumbTrigger");
* sched.scheduleJob(job, trigger);
*
*
* 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
*/
public class NativeJob implements Job {
private final Logger log = LoggerFactory.getLogger(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.
*
* Defaults to true
.
*/
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.
*
* Defaults to false
.
*/
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 Logger getLog() {
return log;
}
private Integer runNativeCommand(String command, String parameters, boolean wait, boolean consumeStreams) throws JobExecutionException {
String[] cmd;
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";
System.arraycopy(args, 0, cmd, 2, args.length);
} else if (osName.equals("Linux")) {
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 = proc.waitFor();
}
// any error message?
} catch (Throwable 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
*/
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(is));
String line;
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) {}
}
}
}
}
}