001 package org.codehaus.plexus.util.cli;
002
003 public class CLICallable implements CommandLineCallable {
004
005 public CLICallable(int timeoutInSeconds, StreamFeeder inputFeeder, StreamPumper outputPumper, StreamPumper errorPumper, Process p, ProcessHook processHook) {
006 this.timeoutInSeconds = timeoutInSeconds;
007 this.inputFeeder = inputFeeder;
008 this.outputPumper = outputPumper;
009 this.errorPumper = errorPumper;
010 this.p = p;
011 this.processHook = processHook;
012 }
013
014 private final int timeoutInSeconds;
015 private final StreamFeeder inputFeeder;
016 private final StreamPumper outputPumper;
017 private final StreamPumper errorPumper;
018 private final Process p;
019 private final ProcessHook processHook;
020
021 @Override
022 public Integer call() throws CommandLineException {
023 try {
024 int returnValue;
025 if (timeoutInSeconds <= 0) {
026 returnValue = p.waitFor();
027 } else {
028 long now = System.currentTimeMillis();
029 long timeoutInMillis = 1000L * timeoutInSeconds;
030 long finish = now + timeoutInMillis;
031 while (CommandLineUtils.isAlive(p) && (System.currentTimeMillis() < finish)) {
032 Thread.sleep(10);
033 }
034 if (CommandLineUtils.isAlive(p)) {
035 throw new InterruptedException("Process timeout out after " + timeoutInSeconds + " seconds");
036 }
037 returnValue = p.exitValue();
038 }
039
040 CommandLineUtils.waitForAllPumpers(inputFeeder, outputPumper, errorPumper);
041
042 if (outputPumper.getException() != null) {
043 throw new CommandLineException("Error inside systemOut parser", outputPumper.getException());
044 }
045
046 if (errorPumper.getException() != null) {
047 throw new CommandLineException("Error inside systemErr parser", errorPumper.getException());
048 }
049
050 return returnValue;
051 } catch (InterruptedException ex) {
052 if (inputFeeder != null) {
053 inputFeeder.disable();
054 }
055 outputPumper.disable();
056 errorPumper.disable();
057 throw new CommandLineTimeOutException("Error while executing external command, process killed.", ex);
058 } finally {
059 ShutdownHookUtils.removeShutdownHook(processHook);
060
061 processHook.run();
062
063 if (inputFeeder != null) {
064 inputFeeder.close();
065 }
066
067 outputPumper.close();
068
069 errorPumper.close();
070 }
071 }
072
073 public int getTimeoutInSeconds() {
074 return timeoutInSeconds;
075 }
076
077 public StreamFeeder getInputFeeder() {
078 return inputFeeder;
079 }
080
081 public StreamPumper getOutputPumper() {
082 return outputPumper;
083 }
084
085 public StreamPumper getErrorPumper() {
086 return errorPumper;
087 }
088
089 public Process getP() {
090 return p;
091 }
092
093 public ProcessHook getProcessHook() {
094 return processHook;
095 }
096
097 }