/* * Copyright 2010-2013 the original author or authors. * * Licensed 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.springframework.cloud.stream.modules.test.gemfire.process.support; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.util.Scanner; import java.util.logging.Logger; import org.springframework.cloud.stream.modules.test.gemfire.support.IOUtils; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** * The ProcessUtils class is a utility class for working with process, or specifically instances * of the Java Process class. * @author John Blum * @see java.io.File * @see java.lang.Process * @see java.lang.management.ManagementFactory * @see java.lang.management.RuntimeMXBean * see com.sun.tools.attach.VirtualMachine * @since 1.5.0 */ public abstract class ProcessUtils { protected static final Logger log = Logger.getLogger(ProcessUtils.class.getName()); protected static final String TERM_TOKEN = "<TERM/>"; public static int currentPid() { RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); String runtimeMXBeanName = runtimeMXBean.getName(); Exception cause = null; if (StringUtils.hasText(runtimeMXBeanName)) { int atSignIndex = runtimeMXBeanName.indexOf('@'); if (atSignIndex > 0) { try { return Integer.parseInt(runtimeMXBeanName.substring(0, atSignIndex)); } catch (NumberFormatException e) { cause = e; } } } throw new PidUnavailableException(String.format("The process ID (PID) is not available (%1$s)!", runtimeMXBeanName), cause); } /* public static boolean isRunning(final int processId) { for (VirtualMachineDescriptor vmDescriptor : VirtualMachine.list()) { if (String.valueOf(processId).equals(vmDescriptor.id())) { return true; } } return false; } */ public static boolean isRunning(final Process process) { try { process.exitValue(); return false; } catch (IllegalThreadStateException ignore) { return true; } } public static void signalStop(final Process process) throws IOException { if (isRunning(process)) { OutputStream processOutputStream = process.getOutputStream(); processOutputStream.write(TERM_TOKEN.concat("\n").getBytes()); processOutputStream.flush(); } } public static void waitForStopSignal() { Scanner in = new Scanner(System.in); while (!TERM_TOKEN.equals(in.next())) ; } public static int findAndReadPid(final File workingDirectory) { Assert.isTrue(workingDirectory != null && workingDirectory.isDirectory(), String.format( "The file system pathname (%1$s) expected to contain a PID file is not a valid directory!", workingDirectory)); File pidFile = findPidFile(workingDirectory); if (pidFile == null) { throw new PidUnavailableException(String.format( "No PID file was found in working directory (%1$s) or any of it's sub-directories!", workingDirectory)); } return readPid(pidFile); } protected static File findPidFile(final File workingDirectory) { Assert.isTrue(workingDirectory != null && workingDirectory.isDirectory(), String.format( "The file system pathname (%1$s) is not valid directory!", workingDirectory)); for (File file : workingDirectory.listFiles(DirectoryPidFileFilter.INSTANCE)) { if (file.isDirectory()) { file = findPidFile(file); } if (PidFileFilter.INSTANCE.accept(file)) { return file; } } return null; } public static int readPid(final File pidFile) { Assert.isTrue(pidFile != null && pidFile.isFile(), String.format( "The file system pathname (%1$s) is not a valid file!", pidFile)); BufferedReader fileReader = null; String pidValue = null; try { fileReader = new BufferedReader(new FileReader(pidFile)); pidValue = String.valueOf(fileReader.readLine()).trim(); return Integer.parseInt(pidValue); } catch (FileNotFoundException e) { throw new PidUnavailableException(String.format("PID file (%1$s) could not be found!", pidFile), e); } catch (IOException e) { throw new PidUnavailableException(String.format("Unable to read PID from file (%1$s)!", pidFile), e); } catch (NumberFormatException e) { throw new PidUnavailableException(String.format( "The value (%1$s) from PID file (%2$s) was not a valid numerical PID!", pidValue, pidFile), e); } finally { IOUtils.close(fileReader); } } public static void writePid(final File pidFile, final int pid) throws IOException { Assert.isTrue(pidFile != null && (pidFile.isFile() || pidFile.createNewFile()), String.format( "The file system pathname (%1$s) in which the PID will be written is not a valid file!", pidFile)); Assert.isTrue(pid > 0, String.format("The PID value (%1$d) must greater than 0!", pid)); PrintWriter fileWriter = new PrintWriter(new BufferedWriter(new FileWriter(pidFile, false), 16), true); try { fileWriter.println(pid); } finally { pidFile.deleteOnExit(); IOUtils.close(fileWriter); } } protected static class DirectoryPidFileFilter extends PidFileFilter { protected static final DirectoryPidFileFilter INSTANCE = new DirectoryPidFileFilter(); @Override public boolean accept(final File pathname) { return (pathname != null && (pathname.isDirectory() || super.accept(pathname))); } } protected static class PidFileFilter implements FileFilter { protected static final PidFileFilter INSTANCE = new PidFileFilter(); @Override public boolean accept(final File pathname) { return (pathname != null && pathname.isFile() && pathname.getName().endsWith(".pid")); } } }