20 package net.sf.gridarta.model.validation.checks;
22 import java.awt.Point;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStreamReader;
27 import java.io.OutputStream;
28 import java.io.OutputStreamWriter;
29 import java.io.Writer;
30 import java.util.concurrent.Semaphore;
31 import java.util.concurrent.TimeUnit;
32 import java.util.regex.Matcher;
33 import java.util.regex.Pattern;
47 import org.jetbrains.annotations.NotNull;
48 import org.jetbrains.annotations.Nullable;
55 public class MapCheckerScriptChecker<G
extends GameObject<G, A, R>, A extends
MapArchObject<A>, R extends
Archetype<G, A, R>> extends
AbstractValidator<G, A, R> implements
MapValidator<G, A, R> {
115 private final String @NotNull []
args;
133 this.args =
args.clone();
135 if (this.args.length < 1) {
136 throw new IllegalArgumentException(
"no script to execute");
139 boolean found =
false;
140 for (
int i = 1; i < this.args.length; i++) {
147 throw new IllegalArgumentException(
"the script to execute doesn't receive the map to check (" +
MAP_PLACEHOLDER +
")");
153 final String[] command =
getCommand(mapModel, errorCollector);
154 if (command ==
null) {
157 final Process process;
159 process = Runtime.getRuntime().exec(command);
160 }
catch (
final IOException ex) {
164 @Nullable
final String output;
167 process.getOutputStream().close();
168 }
catch (
final IOException ex) {
173 output =
runProcess(process, errorCollector, mapModel, command[0]);
177 if (output !=
null) {
178 parseOutput(output, errorCollector, mapModel, command[0]);
192 for (
final String line : lines) {
193 if (!line.isEmpty()) {
195 if (matcher.matches()) {
199 x = Integer.parseInt(matcher.group(1));
200 y = Integer.parseInt(matcher.group(2));
201 }
catch (
final NumberFormatException ignored) {
205 final String message = matcher.group(3);
209 }
catch (
final IndexOutOfBoundsException ignored) {
231 @Nullable String output;
232 final InputStreamReader stdoutReader =
new InputStreamReader(process.getInputStream());
235 final InputStreamReader stderrReader =
new InputStreamReader(process.getErrorStream());
242 if (!
waitForTermination(process, errorCollector, mapModel, command, stdout, stderr)) {
253 stderrReader.close();
254 }
catch (
final IOException ex) {
258 final String stdoutFailure = stdout.
getFailure();
259 if (stdoutFailure !=
null) {
266 stdoutReader.close();
267 }
catch (
final IOException ex) {
285 final Semaphore sem =
new Semaphore(0);
286 final int[] tmp = { -1, };
287 final Runnable runnable = () -> {
292 tmp[0] = process.waitFor();
293 }
catch (
final InterruptedException ignored) {
294 Thread.currentThread().interrupt();
300 final Thread thread =
new Thread(runnable);
307 }
catch (
final InterruptedException ignored) {
316 final String stderrFailure = stderr.getFailure();
317 if (stderrFailure !=
null) {
321 final String stderrOutput = stderr.getOutput();
322 if (!stderrOutput.isEmpty()) {
340 tmpFile = File.createTempFile(
"gridarta",
null);
341 }
catch (
final IOException ex) {
349 final String mapPath =
tmpFile.getPath();
350 final String realMapPath = mapModel.getMapFile() ==
null ?
"" : mapModel.getMapFile().toString();
352 try (OutputStream outputStream =
new FileOutputStream(
tmpFile)) {
357 }
catch (
final IOException ex) {
362 final boolean isWindows = System.getProperty(
"os.name").contains(
"Windows");
363 final String[] result;
367 if (
args[0].toLowerCase().endsWith(
".py")) {
368 result =
new String[
args.length + 1];
372 }
catch (
final IOException ex) {
373 command =
"C:" + File.separator +
"python34" + File.separator +
"python.exe";
374 if (!
new File(command).exists()) {
378 result[index++] =
"\"" + command +
"\"";
380 result =
new String[
args.length];
384 result =
new String[
args.length];
387 }
catch (
final IOException ex) {
391 final String mapPathQuoted = Matcher.quoteReplacement(mapPath);
392 final String realMapPathQuoted = Matcher.quoteReplacement(realMapPath);
393 for (
int i = 1; i <
args.length; i++) {
395 result[index++] = isWindows ?
"\"" + tmp +
"\"" : tmp;
421 private String
getCommand(@NotNull
final String commandName)
throws IOException {
423 if (existingCommand !=
null && existingCommand.exists()) {
424 return existingCommand.getPath();
429 return command.getPath();