MATSIM
ExeRunner.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * ExeRunner.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007, 2008 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.run.gui;
22 
23 import java.io.BufferedReader;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.InputStreamReader;
27 import java.util.Arrays;
28 
29 import javax.swing.JTextArea;
30 
31 import org.apache.logging.log4j.LogManager;
32 import org.apache.logging.log4j.Logger;
33 import org.matsim.core.utils.io.IOUtils;
34 
35 
41 /*package*/ class ExeRunner {
42 
43  /*package*/ final static Logger log = LogManager.getLogger(ExeRunner.class);
44 
45  private final ExternalExecutor executor;
46 
47  public static ExeRunner run(final String[] cmdArgs, final JTextArea stdOut, final JTextArea errOut, final String workingDirectory) {
48  final ExternalExecutor myExecutor = new ExternalExecutor(cmdArgs, stdOut, errOut, workingDirectory);
49  ExeRunner runner = new ExeRunner(myExecutor);
50  myExecutor.start();
51  return runner;
52  }
53 
54  private ExeRunner(ExternalExecutor executor) {
55  this.executor = executor;
56  }
57 
58  public void killProcess() {
59  this.executor.killProcess();
60  }
61 
62  public int waitForFinish() {
63  synchronized (this.executor) {
64  try {
65  this.executor.join();
66  } catch (InterruptedException e) {
67  log.info("Got interrupted while waiting for external exe to finish.", e);
68  }
69  }
70 
71  return this.executor.erg;
72  }
73 
74  private static class ExternalExecutor extends Thread {
75  final String[] cmdArgs;
76  final JTextArea stdOut;
77  final JTextArea errOut;
78  final String workingDirectory;
79  private Process p = null;
80 
81  public int erg = -1;
82 
83  public ExternalExecutor (final String[] cmdArgs, final JTextArea stdOut, final JTextArea errOut, final String workingDirectory) {
84  this.cmdArgs = cmdArgs;
85  this.stdOut = stdOut;
86  this.errOut = errOut;
87  this.workingDirectory = workingDirectory;
88  }
89 
90  public void killProcess() {
91  if (this.p != null) {
92  this.p.destroy();
93  }
94  }
95 
96  @Override
97  public void run() {
98  var processBuilder = new ProcessBuilder();
99  processBuilder.environment().put("MATSIM_GUI", "true"); // add "MATSIM_GUI" to the inherited vars
100 
101  // Copy the MATSIM_GUI_ARGS environment variable to the process environment
102  // these arguments may be used internally by the matsim scenario
103  if (System.getProperty("MATSIM_GUI_ARGS") != null) {
104  processBuilder.environment().put("MATSIM_GUI_ARGS", System.getProperty("MATSIM_GUI_ARGS"));
105  }
106 
107  if (workingDirectory != null) {
108  processBuilder.directory(new File(workingDirectory));
109  }
110  processBuilder.command(cmdArgs);
111 
112  try {
113  this.p = processBuilder.start();
114 
115  BufferedReader in = new BufferedReader(new InputStreamReader(this.p.getInputStream()));
116  BufferedReader err = new BufferedReader(new InputStreamReader(this.p.getErrorStream()));
117 
118  StreamHandler outputHandler = new StreamHandler(in, this.stdOut);
119  outputHandler.start();
120 
121  StreamHandler errorHandler = new StreamHandler(err, this.stdOut, this.errOut);
122  errorHandler.start();
123 
124  log.info("Starting external exe with command: " + Arrays.toString(this.cmdArgs));
125  boolean processRunning = true;
126  while (processRunning) {
127  try {
128  this.p.waitFor();
129  this.erg = this.p.exitValue();
130  log.info("external exe returned " + this.erg);
131  processRunning = false;
132  } catch (InterruptedException e) {
133  log.info("Thread waiting for external exe to finish was interrupted");
134  this.erg = -3;
135  }
136  }
137  try {
138  outputHandler.join();
139  } catch (InterruptedException e) {
140  log.info("got interrupted while waiting for outputHandler to die.", e);
141  }
142  try {
143  errorHandler.join();
144  } catch (InterruptedException e) {
145  log.info("got interrupted while waiting for errorHandler to die.", e);
146  }
147  } catch (IOException e) {
148  log.error("problem running executable.", e);
149  this.erg = -2;
150  }
151  }
152  }
153 
154  static class StreamHandler extends Thread {
155  private final BufferedReader in;
156  private final JTextArea[] textArea;
157 
158  public StreamHandler(final BufferedReader in, final JTextArea... textArea) {
159  this.in = in;
160  this.textArea = textArea;
161  }
162 
163  @Override
164  public void run() {
165  try {
166  String line = null;
167  while ((line = this.in.readLine()) != null) {
168  for (JTextArea out : this.textArea) {
169  out.append(line);
170  out.append(IOUtils.NATIVE_NEWLINE);
171  int length = out.getDocument().getLength();
172  out.setCaretPosition(length);
173 
174  if (length > 512*1024) {
175  out.setText(out.getText().substring(256*1024));
176  }
177  }
178  }
179  } catch (IOException e) {
180  log.info("StreamHandler got interrupted", e);
181  }
182  }
183  }
184 
185 }
ExternalExecutor(final String[] cmdArgs, final JTextArea stdOut, final JTextArea errOut, final String workingDirectory)
Definition: ExeRunner.java:83
static final String NATIVE_NEWLINE
Definition: IOUtils.java:186