package com.rincliu.library.common.persistence.rootmanager.container; import java.io.IOException; import java.io.OutputStream; import com.rincliu.library.common.persistence.rootmanager.Constants; import com.rincliu.library.common.persistence.rootmanager.utils.RootUtils; public abstract class Command { private String[] commands; private boolean isFinished; private int exitCode; private long timeout; private int id; /* Abstract function should be implemented by caller */ public abstract void onUpdate(int id, String message); public abstract void onFinished(int id); public Command(String... commands) { this(Constants.COMMAND_TIMEOUT, commands); } public Command(int timeout, String... commands) { this.id = RootUtils.generateCommandID(); this.timeout = timeout; this.commands = commands; } public int getID() { return id; } public void setExitCode(int code) { synchronized (this) { exitCode = code; isFinished = true; onFinished(id); this.notifyAll(); } } public void terminate(String reason) { try { RootUtils.Log("Terminate all shells with reason " + reason); Shell.closeAll(); setExitCode(-1); } catch (IOException e) { e.printStackTrace(); RootUtils.Log("Terminate all shells and io exception happens"); } } public int waitForFinish(long timeout) throws InterruptedException { synchronized (this) { while (!isFinished) { this.wait(timeout); if (!isFinished) { isFinished = true; RootUtils.Log("Timeout Exception has occurred."); terminate("Timeout Exception"); } } } return exitCode; } public int waitForFinish() throws InterruptedException { synchronized (this) { waitForFinish(timeout); } return exitCode; } public String getCommand() { if (commands == null || commands.length == 0) { return ""; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < commands.length; i++) { sb.append(commands[i]); sb.append('\n'); } String command = sb.toString(); RootUtils.Log("Sending command(s): " + command); return command; } public void writeCommand(OutputStream out) throws IOException { out.write(getCommand().getBytes()); } }