/*
 * Copyright 2015 Red Hat, Inc.
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  and Apache License v2.0 which accompanies this distribution.
 *
 *  The Eclipse Public License is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  The Apache License v2.0 is available at
 *  http://www.opensource.org/licenses/apache2.0.php
 *
 *  You may elect to redistribute this code under either of these licenses.
 *
 *
 * Copyright (c) 2015 The original author or authors
 * ------------------------------------------------------
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution.
 *
 *     The Eclipse Public License is available at
 *     http://www.eclipse.org/legal/epl-v10.html
 *
 *     The Apache License v2.0 is available at
 *     http://www.opensource.org/licenses/apache2.0.php
 *
 * You may elect to redistribute this code under either of these licenses.
 *
 */

package io.vertx.ext.shell.impl;

import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.ext.shell.ShellServer;
import io.vertx.ext.shell.ShellServerOptions;
import io.vertx.ext.shell.command.CommandRegistry;
import io.vertx.ext.shell.command.CommandResolver;
import io.vertx.ext.shell.spi.CommandResolverFactory;
import io.vertx.ext.shell.term.SSHTermOptions;
import io.vertx.ext.shell.ShellService;
import io.vertx.ext.shell.ShellServiceOptions;
import io.vertx.ext.shell.term.TelnetTermOptions;
import io.vertx.ext.shell.term.HttpTermOptions;
import io.vertx.ext.shell.term.impl.SSHServer;
import io.vertx.ext.shell.term.impl.TelnetTermServer;
import io.vertx.ext.shell.term.impl.HttpTermServer;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import java.util.concurrent.atomic.AtomicInteger;

Author:Julien Viet
/** * @author <a href="mailto:julien@julienviet.com">Julien Viet</a> */
public class ShellServiceImpl implements ShellService { private final Vertx vertx; private final ShellServiceOptions options; private final ShellServer server; private final CommandRegistry registry; public ShellServiceImpl(Vertx vertx, ShellServiceOptions options) { this.vertx = vertx; this.options = options; this.server = ShellServer.create(vertx, new ShellServerOptions(options)); this.registry = CommandRegistry.getShared(vertx); } @Override public ShellServer server() { return server; } @Override public void start(Handler<AsyncResult<Void>> startHandler) { // Lookup providers ServiceLoader<CommandResolverFactory> loader = ServiceLoader.load(CommandResolverFactory.class); Iterator<CommandResolverFactory> it = loader.iterator(); List<CommandResolverFactory> factories = new ArrayList<>(); factories.add((vertx, handler) -> handler.handle(Future.succeededFuture(CommandResolver.baseCommands(vertx)))); while (true) { try { if (it.hasNext()) { CommandResolverFactory factory = it.next(); factories.add(factory); } else { break; } } catch (Exception e) { } } // When providers are registered we start the server AtomicInteger count = new AtomicInteger(factories.size()); List<CommandResolver> resolvers = new ArrayList<>(); resolvers.add(registry); Handler<Void> startServer = v -> { if (count.decrementAndGet() == 0) { startServer(resolvers, startHandler); } }; for (CommandResolverFactory factory : factories) { factory.resolver(vertx, ar -> { if (ar.succeeded()) { resolvers.add(ar.result()); } startServer.handle(null); }); } } private void startServer(List<CommandResolver> resolvers, Handler<AsyncResult<Void>> startHandler) { TelnetTermOptions telnetOptions = options.getTelnetOptions(); SSHTermOptions sshOptions = options.getSSHOptions(); HttpTermOptions webOptions = options.getHttpOptions(); if (telnetOptions != null) { server.registerTermServer(new TelnetTermServer(vertx, telnetOptions)); } if (sshOptions != null) { server.registerTermServer(new SSHServer(vertx, sshOptions)); } if (webOptions != null) { server.registerTermServer(new HttpTermServer(vertx, webOptions)); } resolvers.forEach(server::registerCommandResolver); server.listen(startHandler); } @Override public void stop(Handler<AsyncResult<Void>> stopHandler) { server.close(stopHandler); } }