Package restx.specs.shell

Source Code of restx.specs.shell.SpecsShellCommand

package restx.specs.shell;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import jline.console.completer.ArgumentCompleter;
import jline.console.completer.Completer;
import jline.console.completer.StringsCompleter;
import restx.AppSettings;
import restx.Apps;
import restx.core.shell.DepsShellCommand;
import restx.core.shell.ShellAppRunner;
import restx.core.shell.ShellAppRunner.CompileMode;
import restx.factory.Component;
import restx.factory.NamedComponent;
import restx.factory.SingletonFactoryMachine;
import restx.server.simple.simple.SimpleWebServer;
import restx.shell.RestxShell;
import restx.shell.ShellCommandRunner;
import restx.shell.StdShellCommand;

import java.awt.*;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* User: xavierhanin
* Date: 4/10/13
* Time: 4:27 PM
*/
@Component
public class SpecsShellCommand extends StdShellCommand {
    protected SpecsShellCommand() {
        super(ImmutableList.of("spec"), "restx spec commands: server, test, ... ");
    }

    @Override
    protected String resourceMan() {
        return "restx/specs/shell/spec.man";
    }

    @Override
    protected Optional<ShellCommandRunner> doMatch(String line) {
        final List<String> args = splitArgs(line);
        if (args.size() < 2) {
            return Optional.absent();
        }

        switch (args.get(1)) {
            case "server":
                return Optional.<ShellCommandRunner>of(new SpecServerCommandRunner(args));
            case "test":
                if (args.size() > 2 && args.get(2).equals("server")) {
                    return Optional.<ShellCommandRunner>of(new SpecTestServerCommandRunner(args));
                }
                // keep other arguments to run spec test directly with spec test <spec/test/to/run.spec.yaml>
        }

        return Optional.absent();
    }

    @Override
    public Iterable<Completer> getCompleters() {
        return ImmutableList.<Completer>of(
                new ArgumentCompleter(new StringsCompleter("spec"), new StringsCompleter("server", "test"), new StringsCompleter("server")));
    }

    private class SpecTestServerCommandRunner implements ShellCommandRunner {
        private final List<String> args;

        public SpecTestServerCommandRunner(List<String> args) {
            this.args = new ArrayList<>(args);
        }

        @Override
        public void run(final RestxShell shell) throws Exception {
            String basePack;
            boolean quiet = false;
            if (args.size() > 3 && args.get(3).equalsIgnoreCase("--quiet")) {
                args.remove(3);
                quiet = true;
            }

            if (args.size() > 3) {
                basePack = args.get(3);
            } else {
                Optional<String> pack = Apps.with(shell.getFactory().getComponent(AppSettings.class))
                        .guessAppBasePackage(shell.currentLocation());
                if (!pack.isPresent()) {
                    shell.printIn("can't find base app package, src/main/java should contain a AppServer.java source file somewhere",
                            RestxShell.AnsiCodes.ANSI_RED);
                    shell.println("");
                    shell.println("alternatively you can provide the base package with `spec test server <base.pack>`");
                    return;
                }
                basePack = pack.get();
            }
            AppSettings appSettings = shell.getFactory()
                    .concat(new SingletonFactoryMachine<>(-10000, NamedComponent.of(String.class, "restx.app.package", basePack)))
                    .getComponent(AppSettings.class);

            if (!DepsShellCommand.depsUpToDate(shell)) {
                shell.println("restx> deps install");
                new DepsShellCommand().new InstallDepsCommandRunner().run(shell);
            }

            new ShellAppRunner(appSettings, "restx.tests.RestxSpecTestServer",
                    CompileMode.RESOURCES_ONLY, quiet, false, Collections.<String>emptyList()).run(shell);
        }
    }

    private class SpecServerCommandRunner implements ShellCommandRunner {
        private final List<String> args;

        public SpecServerCommandRunner(List<String> args) {
            this.args = args;
        }

        @Override
        public void run(final RestxShell shell) throws Exception {
            final String routerPath;
            if (args.size() > 2) {
                routerPath = args.get(2);
            } else {
                routerPath = "/api";
            }
            int port = 8888;
            if (args.size() > 3) {
                port = Integer.parseInt(args.get(3));
            }

            System.setProperty("restx.factory.load", "onrequest");
            final SimpleWebServer webServer = SimpleWebServer.builder()
                    .setRouterPath(routerPath).setAppBase(".").setPort(port).build();
            webServer.start();
            String uri = webServer.baseUrl() + routerPath;
            shell.printIn("SPECS SERVER READY on " + uri + "/\n", RestxShell.AnsiCodes.ANSI_GREEN);
            shell.println("type `stop` to stop the server, `help` to get help on available commands");

            shell.getConsoleReader().setPrompt("spec-server> ");
            shell.getConsoleReader().addCompleter(new StringsCompleter("stop", "open", "help"));

            boolean exit = false;
            while (!exit) {
                String line = shell.getConsoleReader().readLine().trim();
                switch (line) {
                    case "stop":
                        exit = stop(shell, webServer);
                        break;
                    case "open":
                        openInBrowser(shell, uri);
                        break;
                    case "help":
                        help(shell);
                        break;
                    default:
                        shell.println(
                                "command not found. use `help` to get the list of commands.");
                }
            }
        }

        private void openInBrowser(RestxShell shell, String uri) throws IOException {
            try {
                Desktop.getDesktop().browse(new URI(uri));
            } catch (UnsupportedOperationException e) {
                shell.printIn("can't open browser: " + e.getMessage(), RestxShell.AnsiCodes.ANSI_RED);
            } catch (IOException e) {
                shell.printIn("can't open browser: " + e.getMessage(), RestxShell.AnsiCodes.ANSI_RED);
            } catch (URISyntaxException e) {
                shell.printIn("can't open browser: " + e.getMessage(), RestxShell.AnsiCodes.ANSI_RED);
            }
        }

        private boolean stop(RestxShell consoleReader, SimpleWebServer webServer) {
            boolean exit;
            try {
                consoleReader.println("stopping server...");
                webServer.stop();
                exit = true;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return exit;
        }

        private void help(RestxShell shell) throws IOException {
            shell.printIn("stop", RestxShell.AnsiCodes.ANSI_GREEN);
            shell.println(" - to stop the server");

            shell.printIn("open", RestxShell.AnsiCodes.ANSI_GREEN);
            shell.println(" - open a browser on the spec server");

            shell.printIn("help", RestxShell.AnsiCodes.ANSI_GREEN);
            shell.println(" - this help");

            shell.println("");
            shell.println("to add new routes simply create/edit .spec.yaml file in\n" +
                    "current directory or subdirectories.");
        }
    }
}
TOP

Related Classes of restx.specs.shell.SpecsShellCommand

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.