// Path: src/main/java/com/xebialabs/overcast/command/CommandProcessor.java
// public class CommandProcessor {
// 
//     public static Logger logger = LoggerFactory.getLogger(CommandProcessor.class);
// 
//     private String execDir = ".";
// 
//     private CommandProcessor(final String execDir) {
//         this.execDir = execDir;
//     }
// 
//     private CommandProcessor() {}
// 
//     public static CommandProcessor atLocation(String l) {
//         return new CommandProcessor(l);
//     }
// 
//     public static CommandProcessor atCurrentDir() {
//         return new CommandProcessor();
//     }
// 
//     public CommandResponse run(final Command command) {
// 
//         logger.debug("Executing command {}", command);
// 
//         try {
//             Process p = new ProcessBuilder(command.asList()).directory(new File(execDir)).start();
// 
//             // We do this small trick to have stdout and stderr of the process on the console and
//             // at the same time capture them to strings.
//             ByteArrayOutputStream errors = new ByteArrayOutputStream();
//             ByteArrayOutputStream messages = new ByteArrayOutputStream();
// 
//             Thread t1 = showProcessOutput(new TeeInputStream(p.getErrorStream(), errors), System.err);
//             Thread t2 = showProcessOutput(new TeeInputStream(p.getInputStream(), messages), System.out);
// 
//             int code = p.waitFor();
// 
//             t1.join();
//             t2.join();
// 
//             CommandResponse response = new CommandResponse(code, errors.toString(), messages.toString());
// 
//             if (!response.isSuccessful()) {
//                 throw new NonZeroCodeException(command, response);
//             }
// 
//             return response;
// 
//         } catch (InterruptedException e) {
//             Thread.currentThread().interrupt();
//             throw new RuntimeException("Cannot execute " + command.toString(), e);
//         } catch (IOException e) {
//             throw new RuntimeException("Cannot execute " + command.toString(), e);
//         }
//     }
// 
//     private Thread showProcessOutput(final InputStream from, final PrintStream to) {
//         Thread t = new Thread(() -> {
//             try {
//                 for (; ; ) {
//                     int c = from.read();
//                     if (c == -1)
//                         break;
//                     to.write((char) c);
//                 }
//             } catch (IOException ignore) {
//             }
//         });
//         t.start();
//         return t;
//     }
// 
// }
// 
// Path: src/main/java/com/xebialabs/overcast/command/Command.java
// public static Command aCommand(String executable) {
//     if (executable == null) {
//         throw new IllegalArgumentException("Executable can not be null");
//     }
//     Command c = new Command();
//     c.withPart(executable);
//     return c;
// }


import com.xebialabs.overcast.command.CommandProcessor;
import java.util.EnumSet;
import static com.xebialabs.overcast.command.Command.aCommand;
import static com.xebialabs.overcast.support.virtualbox.VirtualboxState.POWEROFF;
import static com.xebialabs.overcast.support.virtualbox.VirtualboxState.SAVED;
            loadSnapshot(vm, quotedId.substring(1, quotedId.length() - 1));
        }
    }

    /**
     * Shuts down VM.
     */
    public void powerOff(final String vm) {
        execute("controlvm", vm, "poweroff");
    }

    public void start(String vm) {
        execute("startvm", vm, "--type", "headless");
    }

    /**
     * Executes custom VBoxManage command
     */
    public String execute(String... command) {
        return commandProcessor.run(aCommand("VBoxManage").withArguments(command)).getOutput();
    }

    /**
     * Sets extra data on the VM
     */
    public void setExtraData(String vm, String k, String v) {
        execute("setextradata", vm, k, v);
    }

    public String getExtraData(String vm, String k) {
// Path: src/main/java/com/xebialabs/overcast/command/CommandProcessor.java
// public class CommandProcessor {
// 
//     public static Logger logger = LoggerFactory.getLogger(CommandProcessor.class);
// 
//     private String execDir = ".";
// 
//     private CommandProcessor(final String execDir) {
//         this.execDir = execDir;
//     }
// 
//     private CommandProcessor() {}
// 
//     public static CommandProcessor atLocation(String l) {
//         return new CommandProcessor(l);
//     }
// 
//     public static CommandProcessor atCurrentDir() {
//         return new CommandProcessor();
//     }
// 
//     public CommandResponse run(final Command command) {
// 
//         logger.debug("Executing command {}", command);
// 
//         try {
//             Process p = new ProcessBuilder(command.asList()).directory(new File(execDir)).start();
// 
//             // We do this small trick to have stdout and stderr of the process on the console and
//             // at the same time capture them to strings.
//             ByteArrayOutputStream errors = new ByteArrayOutputStream();
//             ByteArrayOutputStream messages = new ByteArrayOutputStream();
// 
//             Thread t1 = showProcessOutput(new TeeInputStream(p.getErrorStream(), errors), System.err);
//             Thread t2 = showProcessOutput(new TeeInputStream(p.getInputStream(), messages), System.out);
// 
//             int code = p.waitFor();
// 
//             t1.join();
//             t2.join();
// 
//             CommandResponse response = new CommandResponse(code, errors.toString(), messages.toString());
// 
//             if (!response.isSuccessful()) {
//                 throw new NonZeroCodeException(command, response);
//             }
// 
//             return response;
// 
//         } catch (InterruptedException e) {
//             Thread.currentThread().interrupt();
//             throw new RuntimeException("Cannot execute " + command.toString(), e);
//         } catch (IOException e) {
//             throw new RuntimeException("Cannot execute " + command.toString(), e);
//         }
//     }
// 
//     private Thread showProcessOutput(final InputStream from, final PrintStream to) {
//         Thread t = new Thread(() -> {
//             try {
//                 for (; ; ) {
//                     int c = from.read();
//                     if (c == -1)
//                         break;
//                     to.write((char) c);
//                 }
//             } catch (IOException ignore) {
//             }
//         });
//         t.start();
//         return t;
//     }
// 
// }
// 
// Path: src/main/java/com/xebialabs/overcast/command/Command.java
// public static Command aCommand(String executable) {
//     if (executable == null) {
//         throw new IllegalArgumentException("Executable can not be null");
//     }
//     Command c = new Command();
//     c.withPart(executable);
//     return c;
// }


// Path: src/main/java/com/xebialabs/overcast/support/virtualbox/VirtualboxDriver.java
import com.xebialabs.overcast.command.CommandProcessor;
import java.util.EnumSet;
import static com.xebialabs.overcast.command.Command.aCommand;
import static com.xebialabs.overcast.support.virtualbox.VirtualboxState.POWEROFF;
import static com.xebialabs.overcast.support.virtualbox.VirtualboxState.SAVED;

            loadSnapshot(vm, quotedId.substring(1, quotedId.length() - 1));
        }
    }

    /**
     * Shuts down VM.
     */
    public void powerOff(final String vm) {
        execute("controlvm", vm, "poweroff");
    }

    public void start(String vm) {
        execute("startvm", vm, "--type", "headless");
    }

    /**
     * Executes custom VBoxManage command
     */
    public String execute(String... command) {
        return commandProcessor.run(aCommand("VBoxManage").withArguments(command)).getOutput();
    }

    /**
     * Sets extra data on the VM
     */
    public void setExtraData(String vm, String k, String v) {
        execute("setextradata", vm, k, v);
    }

    public String getExtraData(String vm, String k) {
        final String prefix = "Value: ";