Autopsy  3.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExecUtil.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2013-2014 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.coreutils;
20 
21 import com.sun.javafx.PlatformUtil;
22 import java.io.BufferedReader;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.io.Writer;
27 import java.util.Date;
28 import java.util.List;
29 import java.util.concurrent.TimeUnit;
30 import java.util.logging.Level;
31 
36 public final class ExecUtil {
37 
38  private static final long DEFAULT_TIMEOUT = 5;
39  private static final TimeUnit DEFAULT_TIMEOUT_UNITS = TimeUnit.SECONDS;
40 
46  public interface ProcessTerminator {
47 
54  boolean shouldTerminateProcess();
55  }
56 
61  public static class TimedProcessTerminator implements ProcessTerminator {
62 
63  private final long startTimeInSeconds;
64  private final long maxRunTimeInSeconds;
65 
72  public TimedProcessTerminator(long maxRunTimeInSeconds) {
73  this.maxRunTimeInSeconds = maxRunTimeInSeconds;
74  this.startTimeInSeconds = (new Date().getTime()) / 1000;
75  }
76 
80  @Override
81  public boolean shouldTerminateProcess() {
82  long currentTimeInSeconds = (new Date().getTime()) / 1000;
83  return (currentTimeInSeconds - this.startTimeInSeconds) > this.maxRunTimeInSeconds;
84  }
85  }
86 
97  public static int execute(ProcessBuilder processBuilder) throws SecurityException, IOException {
98  return ExecUtil.execute(processBuilder, 30, TimeUnit.DAYS, new ProcessTerminator() {
102  @Override
103  public boolean shouldTerminateProcess() {
104  return false;
105  }
106  });
107  }
108 
120  public static int execute(ProcessBuilder processBuilder, ProcessTerminator terminator) throws SecurityException, IOException {
121  return ExecUtil.execute(processBuilder, ExecUtil.DEFAULT_TIMEOUT, ExecUtil.DEFAULT_TIMEOUT_UNITS, terminator);
122  }
123 
137  public static int execute(ProcessBuilder processBuilder, long timeOut, TimeUnit units, ProcessTerminator terminator) throws SecurityException, IOException {
138  Process process = processBuilder.start();
139  try {
140  do {
141  process.waitFor(timeOut, units);
142  if (process.isAlive() && terminator.shouldTerminateProcess()) {
143  killProcess(process);
144  }
145  } while (process.isAlive());
146  } catch (InterruptedException ex) {
147  if (process.isAlive()) {
148  killProcess(process);
149  }
150  Logger.getLogger(ExecUtil.class.getName()).log(Level.INFO, "Thread interrupted while running {0}", processBuilder.command().get(0)); // NON-NLS
151  Thread.currentThread().interrupt();
152  }
153  return process.exitValue();
154  }
155 
161  public static void killProcess(Process process) {
162  if (process == null) {
163  return;
164  }
165 
166  try {
167  if (PlatformUtil.isWindows()) {
168  Win32Process parentProcess = new Win32Process(process);
169  List<Win32Process> children = parentProcess.getChildren();
170 
171  children.stream().forEach((child) -> {
172  child.terminate();
173  });
174  parentProcess.terminate();
175  } else {
176  process.destroyForcibly();
177  }
178  } catch (Exception ex) {
179  logger.log(Level.WARNING, "Error occurred when attempting to kill process: {0}", ex.getMessage()); // NON-NLS
180  }
181  }
182 
186  private static final Logger logger = Logger.getLogger(ExecUtil.class.getName());
187  private Process proc = null;
191  private int exitValue = -100;
192 
202  @Deprecated
203  public synchronized String execute(final String aCommand, final String... params) throws IOException, InterruptedException {
204  // build command array
205  String[] arrayCommand = new String[params.length + 1];
206  arrayCommand[0] = aCommand;
207 
208  StringBuilder arrayCommandToLog = new StringBuilder();
209  arrayCommandToLog.append(aCommand).append(" ");
210 
211  for (int i = 1; i < arrayCommand.length; i++) {
212  arrayCommand[i] = params[i - 1];
213  arrayCommandToLog.append(arrayCommand[i]).append(" ");
214  }
215 
216  final Runtime rt = Runtime.getRuntime();
217  logger.log(Level.INFO, "Executing {0}", arrayCommandToLog.toString()); //NON-NLS
218 
219  proc = rt.exec(arrayCommand);
220 
221  //stderr redirect
222  errorStringRedirect = new ExecUtil.StreamToStringRedirect(proc.getErrorStream(), "ERROR"); //NON-NLS
223  errorStringRedirect.start();
224 
225  //stdout redirect
226  outputStringRedirect = new ExecUtil.StreamToStringRedirect(proc.getInputStream(), "OUTPUT"); //NON-NLS
227  outputStringRedirect.start();
228 
229  //wait for process to complete and capture error core
230  this.exitValue = proc.waitFor();
231 
232  // wait for output redirectors to finish writing / reading
233  outputStringRedirect.join();
234  errorStringRedirect.join();
235 
236  return outputStringRedirect.getOutput();
237  }
238 
248  @Deprecated
249  public synchronized void execute(final Writer stdoutWriter, final String aCommand, final String... params) throws IOException, InterruptedException {
250 
251  // build command array
252  String[] arrayCommand = new String[params.length + 1];
253  arrayCommand[0] = aCommand;
254 
255  StringBuilder arrayCommandToLog = new StringBuilder();
256  arrayCommandToLog.append(aCommand).append(" ");
257 
258  for (int i = 1; i < arrayCommand.length; i++) {
259  arrayCommand[i] = params[i - 1];
260  arrayCommandToLog.append(arrayCommand[i]).append(" ");
261  }
262 
263  final Runtime rt = Runtime.getRuntime();
264  logger.log(Level.INFO, "Executing {0}", arrayCommandToLog.toString()); //NON-NLS
265 
266  proc = rt.exec(arrayCommand);
267 
268  //stderr redirect
269  errorStringRedirect = new ExecUtil.StreamToStringRedirect(proc.getErrorStream(), "ERROR"); //NON-NLS
270  errorStringRedirect.start();
271 
272  //stdout redirect
273  outputWriterRedirect = new ExecUtil.StreamToWriterRedirect(proc.getInputStream(), stdoutWriter);
274  outputWriterRedirect.start();
275 
276  //wait for process to complete and capture error core
277  this.exitValue = proc.waitFor();
278  logger.log(Level.INFO, "{0} exit value: {1}", new Object[]{aCommand, exitValue}); //NON-NLS
279 
280  // wait for them to finish writing / reading
281  outputWriterRedirect.join();
282  errorStringRedirect.join();
283 
284  //gc process with its streams
285  //proc = null;
286  }
287 
291  @Deprecated
292  public synchronized void stop() {
293 
294  if (errorStringRedirect != null) {
295  errorStringRedirect.stopRun();
296  errorStringRedirect = null;
297  }
298 
299  if (outputStringRedirect != null) {
300  outputStringRedirect.stopRun();
301  outputStringRedirect = null;
302  }
303 
304  if (outputWriterRedirect != null) {
305  outputWriterRedirect.stopRun();
306  outputWriterRedirect = null;
307  }
308 
309  if (proc != null) {
310  proc.destroy();
311  proc = null;
312  }
313  }
314 
321  @Deprecated
322  synchronized public int getExitValue() {
323  return this.exitValue;
324  }
325 
332  private static class StreamToStringRedirect extends Thread {
333 
334  private static final Logger logger = Logger.getLogger(StreamToStringRedirect.class.getName());
335  private final InputStream is;
336  private final StringBuffer output = new StringBuffer();
337  private volatile boolean doRun = false;
338 
339  StreamToStringRedirect(final InputStream anIs, final String aType) {
340  this.is = anIs;
341  this.doRun = true;
342  }
343 
350  @Override
351  public final void run() {
352  final String SEP = System.getProperty("line.separator");
353  InputStreamReader isr;
354  BufferedReader br = null;
355  try {
356  isr = new InputStreamReader(this.is);
357  br = new BufferedReader(isr);
358  String line = null;
359  while (doRun && (line = br.readLine()) != null) {
360  this.output.append(line).append(SEP);
361  }
362  } catch (final IOException ex) {
363  logger.log(Level.WARNING, "Error redirecting stream to string buffer", ex); //NON-NLS
364  } finally {
365  if (br != null) {
366  try {
367  br.close();
368  } catch (IOException ex) {
369  logger.log(Level.SEVERE, "Error closing stream reader", ex); //NON-NLS
370  }
371  }
372  }
373  }
374 
379  public void stopRun() {
380  doRun = false;
381  }
382 
389  public final String getOutput() {
390  return this.output.toString();
391  }
392  }
393 
402  private static class StreamToWriterRedirect extends Thread {
403 
404  private static final Logger logger = Logger.getLogger(StreamToStringRedirect.class.getName());
405  private final InputStream is;
406  private volatile boolean doRun = false;
407  private Writer writer = null;
408 
409  StreamToWriterRedirect(final InputStream anIs, final Writer writer) {
410  this.is = anIs;
411  this.writer = writer;
412  this.doRun = true;
413  }
414 
421  @Override
422  public final void run() {
423  final String SEP = System.getProperty("line.separator");
424  InputStreamReader isr;
425  BufferedReader br = null;
426  try {
427  isr = new InputStreamReader(this.is);
428  br = new BufferedReader(isr);
429  String line = null;
430  while (doRun && (line = br.readLine()) != null) {
431  writer.append(line).append(SEP);
432  }
433  } catch (final IOException ex) {
434  logger.log(Level.SEVERE, "Error reading output and writing to file writer", ex); //NON-NLS
435  } finally {
436  try {
437  if (doRun) {
438  writer.flush();
439  }
440  if (br != null) {
441  br.close();
442  }
443 
444  } catch (IOException ex) {
445  logger.log(Level.SEVERE, "Error flushing file writer", ex); //NON-NLS
446  }
447  }
448  }
449 
454  public void stopRun() {
455  doRun = false;
456  }
457  }
458 }
ExecUtil.StreamToStringRedirect errorStringRedirect
Definition: ExecUtil.java:188
static int execute(ProcessBuilder processBuilder, ProcessTerminator terminator)
Definition: ExecUtil.java:120
ExecUtil.StreamToWriterRedirect outputWriterRedirect
Definition: ExecUtil.java:190
static int execute(ProcessBuilder processBuilder)
Definition: ExecUtil.java:97
static final TimeUnit DEFAULT_TIMEOUT_UNITS
Definition: ExecUtil.java:39
synchronized void execute(final Writer stdoutWriter, final String aCommand, final String...params)
Definition: ExecUtil.java:249
ExecUtil.StreamToStringRedirect outputStringRedirect
Definition: ExecUtil.java:189
static void killProcess(Process process)
Definition: ExecUtil.java:161
static int execute(ProcessBuilder processBuilder, long timeOut, TimeUnit units, ProcessTerminator terminator)
Definition: ExecUtil.java:137
synchronized String execute(final String aCommand, final String...params)
Definition: ExecUtil.java:203
static Logger getLogger(String name)
Definition: Logger.java:131

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.