// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/cmds/ListCommand.java
// public class ListCommand extends BackendCommand {
// 
//     public ListCommand() {
//         super(BackendCommandType.LIST);
//     }
// }
// 
// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/cmds/StartCommand.java
// public class StartCommand extends BackendCommand {
// 
//     /**
//      * Whether the backend was started for this command.
//      * (If not, the backend prints a "already running" message.
//      */
//     private final boolean backendLaunched;
// 
//     public StartCommand(boolean backendLaunched) {
//         super(BackendCommandType.START);
//         this.backendLaunched = backendLaunched;
//     }
// 
//     public boolean isBackendLaunched() {
//         return backendLaunched;
//     }
// }
// 
// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/cmds/StatusCommand.java
// public class StatusCommand extends BackendCommand {
// 
//     public StatusCommand() {
//         super(BackendCommandType.NOP);
//     }
// 
//     @Override
//     public boolean startBackendOnSendError() {
//         return false;
//     }
// 
//     @Override
//     public void onFrontendResult(boolean deliveredToBackend) {
//         if (deliveredToBackend) {
//             CLITools.out.println("LanXchange is running in the background.");
//         } else {
//             CLITools.out.println("LanXchange backend is NOT running.");
//         }
//     }
// }
// 
// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/cmds/StopCommand.java
// public class StopCommand extends BackendCommand {
// 
//     private final boolean force;
// 
//     public StopCommand(boolean force) {
//         super(BackendCommandType.STOP);
//         this.force = force;
//     }
// 
//     public boolean isForce() {
//         return force;
//     }
// 
//     @Override
//     public boolean startBackendOnSendError() {
//         return false;
//     }
// 
//     @Override
//     public void onFrontendResult(boolean deliveredToBackend) {
//         if (!deliveredToBackend) {
//             CLITools.out.println("Not running.");
//         }
//     }
// }
// 
// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/ui/CLITools.java
// public final class CLITools {
// 
//     /**
//      * This is the original System.out out.
//      * LanXchange may change System.out for logging purposes, but the cli gui must still be able to print to stdout.
//      */
//     public static final PrintStream out = new PrintStream(new FileOutputStream(FileDescriptor.out));
// }


import de.tobifleig.lxc.plaf.cli.cmds.ListCommand;
import de.tobifleig.lxc.plaf.cli.cmds.StartCommand;
import de.tobifleig.lxc.plaf.cli.cmds.StatusCommand;
import de.tobifleig.lxc.plaf.cli.cmds.StopCommand;
import de.tobifleig.lxc.plaf.cli.ui.CLITools;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
                return true;
            } catch (ConnectException e) {
                // backend might be in startup, retry with exponential backoff
                CLITools.out.println("DEBUG: Submisson failed, retry in " + reconnectDelay);
                try {
                    Thread.sleep(reconnectDelay);
                } catch (InterruptedException e1) {
                    // ignore
                }
                reconnectDelay *= 2;
            } catch (IOException e) {
                // unexpected
                // TODO!
                return false;
            }
        } while (awaitBackendStartup && reconnectDelay <= RECONNECT_DELAY_MS_MAX);
        // TODO unreachable even after waiting quite a while!
        CLITools.out.println("DEBUG: Submission failed, retry time limit exceeded - giving up.");
        return false;
    }

    private static BackendCommand parseList(String[] data) {
        if (verifyCommandLength(data, 0, 0)) {
            return new ListCommand();
        }
        return null;
    }

    private static BackendCommand parseStart(String[] data, boolean alreadyStarted) {
        if (verifyCommandLength(data, 0, 0)) {
// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/cmds/ListCommand.java
// public class ListCommand extends BackendCommand {
// 
//     public ListCommand() {
//         super(BackendCommandType.LIST);
//     }
// }
// 
// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/cmds/StartCommand.java
// public class StartCommand extends BackendCommand {
// 
//     /**
//      * Whether the backend was started for this command.
//      * (If not, the backend prints a "already running" message.
//      */
//     private final boolean backendLaunched;
// 
//     public StartCommand(boolean backendLaunched) {
//         super(BackendCommandType.START);
//         this.backendLaunched = backendLaunched;
//     }
// 
//     public boolean isBackendLaunched() {
//         return backendLaunched;
//     }
// }
// 
// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/cmds/StatusCommand.java
// public class StatusCommand extends BackendCommand {
// 
//     public StatusCommand() {
//         super(BackendCommandType.NOP);
//     }
// 
//     @Override
//     public boolean startBackendOnSendError() {
//         return false;
//     }
// 
//     @Override
//     public void onFrontendResult(boolean deliveredToBackend) {
//         if (deliveredToBackend) {
//             CLITools.out.println("LanXchange is running in the background.");
//         } else {
//             CLITools.out.println("LanXchange backend is NOT running.");
//         }
//     }
// }
// 
// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/cmds/StopCommand.java
// public class StopCommand extends BackendCommand {
// 
//     private final boolean force;
// 
//     public StopCommand(boolean force) {
//         super(BackendCommandType.STOP);
//         this.force = force;
//     }
// 
//     public boolean isForce() {
//         return force;
//     }
// 
//     @Override
//     public boolean startBackendOnSendError() {
//         return false;
//     }
// 
//     @Override
//     public void onFrontendResult(boolean deliveredToBackend) {
//         if (!deliveredToBackend) {
//             CLITools.out.println("Not running.");
//         }
//     }
// }
// 
// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/ui/CLITools.java
// public final class CLITools {
// 
//     /**
//      * This is the original System.out out.
//      * LanXchange may change System.out for logging purposes, but the cli gui must still be able to print to stdout.
//      */
//     public static final PrintStream out = new PrintStream(new FileOutputStream(FileDescriptor.out));
// }


// Path: modules/cli/src/main/java/de/tobifleig/lxc/plaf/cli/CLIFrontend.java
import de.tobifleig.lxc.plaf.cli.cmds.ListCommand;
import de.tobifleig.lxc.plaf.cli.cmds.StartCommand;
import de.tobifleig.lxc.plaf.cli.cmds.StatusCommand;
import de.tobifleig.lxc.plaf.cli.cmds.StopCommand;
import de.tobifleig.lxc.plaf.cli.ui.CLITools;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;

                return true;
            } catch (ConnectException e) {
                // backend might be in startup, retry with exponential backoff
                CLITools.out.println("DEBUG: Submisson failed, retry in " + reconnectDelay);
                try {
                    Thread.sleep(reconnectDelay);
                } catch (InterruptedException e1) {
                    // ignore
                }
                reconnectDelay *= 2;
            } catch (IOException e) {
                // unexpected
                // TODO!
                return false;
            }
        } while (awaitBackendStartup && reconnectDelay <= RECONNECT_DELAY_MS_MAX);
        // TODO unreachable even after waiting quite a while!
        CLITools.out.println("DEBUG: Submission failed, retry time limit exceeded - giving up.");
        return false;
    }

    private static BackendCommand parseList(String[] data) {
        if (verifyCommandLength(data, 0, 0)) {
            return new ListCommand();
        }
        return null;
    }

    private static BackendCommand parseStart(String[] data, boolean alreadyStarted) {
        if (verifyCommandLength(data, 0, 0)) {
            return new StartCommand(alreadyStarted);