001package org.nuxeo.launcher.process;
002
003import java.io.IOException;
004import java.util.List;
005import java.util.regex.Matcher;
006import java.util.regex.Pattern;
007
008import org.apache.commons.io.IOUtils;
009
010/**
011 * {@link ProcessManager} implementation for Windows.
012 * <p>
013 * Requires wmic.exe and taskkill.exe, that should be available at least on Windows XP, Windows Vista, and Windows 7
014 * (except Home versions).
015 */
016public class WindowsProcessManager implements ProcessManager {
017
018    protected static final boolean PID_ENABLED = true;
019
020    private static final Pattern PROCESS_GET_LINE = Pattern.compile("^(.*?)\\s+(\\d+)\\s*$");
021
022    @Override
023    public String findPid(String regex) throws IOException {
024        Pattern commandPattern = Pattern.compile(regex);
025        for (String line : execute("wmic", "process", "get", "CommandLine,ProcessId")) {
026            Matcher lineMatcher = PROCESS_GET_LINE.matcher(line);
027            if (lineMatcher.matches()) {
028                String commandLine = lineMatcher.group(1);
029                String pid = lineMatcher.group(2);
030                Matcher commandMatcher = commandPattern.matcher(commandLine);
031                if (commandMatcher.find()) {
032                    return pid;
033                }
034            }
035        }
036        return null;
037    }
038
039    @Override
040    public void kill(Process process, String pid) throws IOException {
041        execute("taskkill", "/t", "/f", "/pid", pid);
042    }
043
044    public boolean isUsable() {
045        try {
046            execute("wmic", "quit");
047            execute("taskkill", "/?");
048            return true;
049        } catch (IOException ioException) {
050            return false;
051        }
052    }
053
054    private List<String> execute(String... command) throws IOException {
055        Process process = new ProcessBuilder(command).start();
056        process.getOutputStream().close(); // don't wait for stdin
057        List<String> lines = IOUtils.readLines(process.getInputStream());
058        try {
059            process.waitFor();
060        } catch (InterruptedException interruptedException) {
061            // sorry for the interruption
062        }
063        return lines;
064    }
065
066    @Override
067    public boolean canFindPid() {
068        return PID_ENABLED;
069    }
070
071}