package chatty.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Provides functions to start processes and store a list of them.
*
* @author tduva
*/
public class ProcessManager {
// Used to make an id for currently running processes
private static final AtomicInteger lastId = new AtomicInteger();
// Store currently running processes
private static final Map<Integer, Proc> processes
= Collections.synchronizedMap(new TreeMap<Integer, Proc>());
/**
* Handle input from the /proc command.
*
* @param input The parameters to the command
* @return Message back to the user
*/
public static String command(String input) {
if (input == null || input.isEmpty()) {
return "Invalid input.";
}
String[] split = input.split(" ", 2);
String command = split[0];
String parameter = null;
if (split.length == 2) {
parameter = split[1];
}
if (command.equals("exec")) {
execute(parameter, "Custom");
return "Trying to start process.";
}
else if (command.equals("kill")) {
try {
if (kill(Integer.parseInt(parameter))) {
return "Trying to kill process.";
}
return "No process with this id.";
} catch (NumberFormatException ex) {
return "Invalid parameter.";
}
}
else if (command.equals("list")) {
Collection<String> list = getList();
StringBuilder result = new StringBuilder("Currently "+list.size()+" processes.");
for (String p : list) {
result.append("\n");
result.append(p);
}
return result.toString();
}
return "Invalid input.";
}
/**
* Execute the given process and parameters.
*
* @param command The process and parameters
* @param label For debug output
*/
public static void execute(String command, String label) {
final int id = lastId.incrementAndGet();
Proc proc = new Proc(command, new Proc.ProcListener() {
@Override
public void processStarted(Proc p) {
processes.put(id, p);
}
@Override
public void message(Proc p, String message) {
}
@Override
public void processFinished(Proc p, int exitValue) {
processes.remove(id);
}
}, label+"/"+id);
proc.start();
}
/**
* Try to kill the process with the given id, if running.
*
* @param id The id as created in execute()
* @return true if the id was of a running process, false otherwise (doesn't
* give any indiciation if killing the process actually worked)
*/
public static boolean kill(int id) {
Proc proc = processes.get(id);
if (proc != null) {
proc.kill();
return true;
}
return false;
}
/**
* Return a list of human-readable information on all running processes.
*
* @return
*/
public static Collection<String> getList() {
Collection<String> result = new ArrayList<>();
for (int id : processes.keySet()) {
Proc p = processes.get(id);
result.add(id+": "+p.toString());
}
return result;
}
}