| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.commons.rng.examples.stress; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * Utility methods for a {@link Process}. |
| */ |
| final class ProcessUtils { |
| /** The timeout to wait for the process exit value in milliseconds. */ |
| private static final long DEFAULT_TIMEOUT_MILLIS = 1000L; |
| |
| /** No public construction. */ |
| private ProcessUtils() {} |
| |
| /** |
| * Check the executable exists and has execute permissions. |
| * |
| * @param executable The executable. |
| * @throws ApplicationException If the executable is invalid. |
| */ |
| static void checkExecutable(File executable) { |
| if (!executable.exists() || |
| !executable.canExecute()) { |
| throw new ApplicationException("Program is not executable: " + executable); |
| } |
| } |
| |
| /** |
| * Check the output directory exists and has write permissions. |
| * |
| * @param fileOutputPrefix The file output prefix. |
| * @throws ApplicationException If the output directory is invalid. |
| */ |
| static void checkOutputDirectory(File fileOutputPrefix) { |
| final File reportDir = fileOutputPrefix.getAbsoluteFile().getParentFile(); |
| if (!reportDir.exists() || |
| !reportDir.isDirectory() || |
| !reportDir.canWrite()) { |
| throw new ApplicationException("Invalid output directory: " + reportDir); |
| } |
| } |
| |
| /** |
| * Builds the command for the sub-process. |
| * |
| * @param executable The executable file. |
| * @param executableArguments The executable arguments. |
| * @return the command |
| * @throws ApplicationException If the executable path cannot be resolved |
| */ |
| static List<String> buildSubProcessCommand(File executable, |
| List<String> executableArguments) { |
| final ArrayList<String> command = new ArrayList<>(); |
| try { |
| command.add(executable.getCanonicalPath()); |
| } catch (final IOException ex) { |
| // Not expected to happen as the file has been tested to exist |
| throw new ApplicationException("Cannot resolve executable path: " + ex.getMessage(), ex); |
| } |
| command.addAll(executableArguments); |
| return command; |
| } |
| |
| /** |
| * Get the exit value from the process, waiting at most for 1 second, otherwise kill the process |
| * and return {@code null}. |
| * |
| * <p>This should be used when it is expected the process has completed.</p> |
| * |
| * @param process The process. |
| * @return The exit value. |
| * @see Process#destroy() |
| */ |
| static Integer getExitValue(Process process) { |
| return getExitValue(process, DEFAULT_TIMEOUT_MILLIS); |
| } |
| |
| /** |
| * Get the exit value from the process, waiting at most for the given time, otherwise |
| * kill the process and return {@code null}. |
| * |
| * <p>This should be used when it is expected the process has completed.</p> |
| * |
| * @param process The process. |
| * @param timeoutMillis The timeout (in milliseconds). |
| * @return The exit value. |
| * @see Process#destroy() |
| */ |
| static Integer getExitValue(Process process, long timeoutMillis) { |
| final long startTime = System.currentTimeMillis(); |
| long remaining = timeoutMillis; |
| |
| while (remaining > 0) { |
| try { |
| return process.exitValue(); |
| } catch (final IllegalThreadStateException ex) { |
| try { |
| Thread.sleep(Math.min(remaining + 1, 100)); |
| } catch (final InterruptedException e) { |
| // Reset interrupted status and stop waiting |
| Thread.currentThread().interrupt(); |
| break; |
| } |
| } |
| remaining = timeoutMillis - (System.currentTimeMillis() - startTime); |
| } |
| |
| // Not finished so kill it |
| process.destroy(); |
| |
| return null; |
| } |
| } |