All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.vertx.ext.shell.command.impl.CommandRegistryImpl Maven / Gradle / Ivy

There is a newer version: 5.0.0.CR1
Show newest version
/*
 * 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.command.impl;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.AsyncResult;
import io.vertx.core.Closeable;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.impl.VertxInternal;
import io.vertx.ext.shell.command.AnnotatedCommand;
import io.vertx.ext.shell.command.Command;
import io.vertx.ext.shell.command.CommandRegistry;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author Julien Viet
 */
public class CommandRegistryImpl implements CommandRegistry {

  private static final Map registries = new ConcurrentHashMap<>();

  public static CommandRegistry get(Vertx vertx) {
    return registries.computeIfAbsent(vertx, v -> new CommandRegistryImpl((VertxInternal) vertx));
  }

  final VertxInternal vertx;
  final ConcurrentHashMap commandMap = new ConcurrentHashMap<>();
  final Closeable hook;
  private volatile boolean closed;

  public CommandRegistryImpl(VertxInternal vertx) {
    this.vertx = vertx;
    hook = completionHandler -> {
      try {
        doClose();
        registries.remove(vertx);
      } catch (Exception e) {
        completionHandler.handle(Future.failedFuture(e));
        return;
      }
      completionHandler.handle(Future.succeededFuture());
    };
    vertx.addCloseHook(hook);
  }

  private void doClose() {
    closed = true;
  }

  public boolean isClosed() {
    return closed;
  }

  public List commands() {
    return new ArrayList<>(commandMap.values().stream().map(reg -> reg.command).collect(Collectors.toList()));
  }

  @Override
  public Future registerCommand(Class command) {
    return registerCommand(Command.create(vertx, command));
  }

  @Override
  public CommandRegistry registerCommand(Class command, Handler> completionHandler) {
    return registerCommand(Command.create(vertx, command), completionHandler);
  }

  @Override
  public Future registerCommand(Command command) {
    Promise promise = Promise.promise();
    registerCommand(command, promise);
    return promise.future();
  }

  @Override
  public CommandRegistry registerCommand(Command command, Handler> completionHandler) {
    return registerCommands(Collections.singletonList(command), ar -> {
      if (completionHandler != null) {
        if (ar.succeeded()) {
          completionHandler.handle(Future.succeededFuture(ar.result().get(0)));
        } else {
          completionHandler.handle(Future.failedFuture(ar.cause()));
        }
      }
    });
  }

  @Override
  public Future> registerCommands(List commands) {
    Promise> promise = Promise.promise();
    registerCommands(commands, promise);
    return promise.future();
  }

  @Override
  public CommandRegistry registerCommands(List commands, Handler>> doneHandler) {
    if (closed) {
      throw new IllegalStateException();
    }
    vertx.deployVerticle(new AbstractVerticle() {

      @Override
      public void start() throws Exception {
        Map newReg = new HashMap<>();
        for (Command command : commands) {
          String name = command.name();
          if (commandMap.containsKey(name)) {
            throw new Exception("Command " + name + " already registered");
          }
          CommandRegistration registration = new CommandRegistration(command, deploymentID());
          newReg.put(name, registration);
        }
        commandMap.putAll(newReg);
      }

      @Override
      public void stop() throws Exception {
        String deploymentId = deploymentID();
        commandMap.values().removeIf(reg -> deploymentId.equals(reg.deploymendID));
      }
    }, ar -> {
      if (ar.succeeded()) {
        List regs = commandMap.values().
            stream().
            filter(reg -> ar.result().equals(reg.deploymendID)).
            map(reg -> reg.command).
            collect(Collectors.toList());
        doneHandler.handle(Future.succeededFuture(regs));
      } else {
        doneHandler.handle(Future.failedFuture(ar.cause()));
      }
    });
    return this;
  }

  @Override
  public Future unregisterCommand(String commandName) {
    Promise promise = Promise.promise();
    unregisterCommand(commandName, promise);
    return promise.future();
  }

  @Override
  public CommandRegistry unregisterCommand(String name, Handler> completionHandler) {
    if (closed) {
      throw new IllegalStateException();
    }
    CommandRegistration registration = commandMap.remove(name);
    if (registration != null) {
      String deploymendID = registration.deploymendID;
      if (deploymendID != null) {
        if (commandMap.values().stream().noneMatch(reg -> deploymendID.equals(reg.deploymendID))) {
          if (completionHandler != null) {
            vertx.undeploy(deploymendID, completionHandler);
          }
          return this;
        }
      }
      if (completionHandler != null) {
        completionHandler.handle(Future.succeededFuture());
      }
    } else if (completionHandler != null) {
      completionHandler.handle(Future.failedFuture("Command " + name + " not registered"));
    }
    return this;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy