mirror of
https://github.com/jlengrand/vert.x.git
synced 2026-03-10 08:51:19 +00:00
@@ -267,4 +267,18 @@ public interface CLI {
|
||||
*/
|
||||
@GenIgnore
|
||||
CLI usage(StringBuilder builder, String prefix);
|
||||
|
||||
/**
|
||||
* @return the CLI priority.
|
||||
*/
|
||||
int getPriority();
|
||||
|
||||
/**
|
||||
* Sets the priority of the CLI.
|
||||
*
|
||||
* @param priority the priority
|
||||
* @return the current {@link CLI} instance
|
||||
*/
|
||||
@Fluent
|
||||
CLI setPriority(int priority);
|
||||
}
|
||||
|
||||
@@ -48,10 +48,11 @@ public class CLIConfigurator {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("The command cannot be defined, the @Name annotation is missing.");
|
||||
}
|
||||
if (name.value() == null || name.value().isEmpty()) {
|
||||
if (name.value().isEmpty()) {
|
||||
throw new IllegalArgumentException("The command cannot be defined, the @Name value is empty or null.");
|
||||
}
|
||||
cli.setName(name.value());
|
||||
cli.setPriority(name.priority());
|
||||
|
||||
if (summary != null) {
|
||||
cli.setSummary(summary.value());
|
||||
|
||||
@@ -32,4 +32,9 @@ public @interface Name {
|
||||
*/
|
||||
String value();
|
||||
|
||||
/**
|
||||
* The command priority. If more than 1 with same name are available on the classpath the one with highest priority
|
||||
* replaces the existing.
|
||||
*/
|
||||
int priority() default 0;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.stream.Collectors;
|
||||
public class DefaultCLI implements CLI {
|
||||
|
||||
protected String name;
|
||||
protected int priority;
|
||||
protected String description;
|
||||
protected String summary;
|
||||
protected boolean hidden;
|
||||
@@ -238,4 +239,15 @@ public class DefaultCLI implements CLI {
|
||||
new UsageMessageFormatter().usage(builder, prefix, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CLI setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public class ReflectionUtils {
|
||||
|
||||
public static <T> T newInstance(Class<T> clazz) {
|
||||
try {
|
||||
return clazz.newInstance();
|
||||
return clazz.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Cannot instantiate " + clazz.getName(), e);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -115,7 +116,18 @@ public class VertxCommandLauncher extends UsageMessageFormatter {
|
||||
protected void load() {
|
||||
for (CommandFactoryLookup lookup : lookups) {
|
||||
Collection<CommandFactory<?>> commands = lookup.lookup();
|
||||
commands.forEach(this::register);
|
||||
commands.forEach(factory -> {
|
||||
CLI cli = factory.define();
|
||||
CommandRegistration previous = commandByName.get(cli.getName());
|
||||
if (previous == null) {
|
||||
commandByName.put(cli.getName(), new CommandRegistration(factory, cli));
|
||||
} else {
|
||||
// command already registered, in this case we will replace IFF the priority is higher
|
||||
if (cli.getPriority() > previous.cli.getPriority()) {
|
||||
commandByName.put(cli.getName(), new CommandRegistration(factory, cli));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +137,7 @@ public class VertxCommandLauncher extends UsageMessageFormatter {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings("unchecked")
|
||||
public VertxCommandLauncher register(Class<? extends Command> clazz) {
|
||||
DefaultCommandFactory factory = new DefaultCommandFactory(clazz);
|
||||
@@ -133,6 +146,14 @@ public class VertxCommandLauncher extends UsageMessageFormatter {
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public VertxCommandLauncher register(Class<? extends Command> clazz, Supplier<? extends Command> supplier) {
|
||||
DefaultCommandFactory factory = new DefaultCommandFactory(clazz, supplier);
|
||||
CLI cli = factory.define();
|
||||
commandByName.put(cli.getName(), new CommandRegistration(factory, cli));
|
||||
return this;
|
||||
}
|
||||
|
||||
public VertxCommandLauncher unregister(String name) {
|
||||
commandByName.remove(name);
|
||||
return this;
|
||||
@@ -215,6 +236,7 @@ public class VertxCommandLauncher extends UsageMessageFormatter {
|
||||
if (main != null) {
|
||||
context.put("Main", main);
|
||||
context.put("Main-Class", main.getClass().getName());
|
||||
context.put("Default-Verticle-Factory", getFromManifest("Default-Verticle-Factory"));
|
||||
}
|
||||
|
||||
CLIConfigurator.inject(evaluated, cmd);
|
||||
@@ -409,21 +431,24 @@ public class VertxCommandLauncher extends UsageMessageFormatter {
|
||||
}
|
||||
|
||||
protected String getCommandFromManifest() {
|
||||
return getFromManifest("Main-Command");
|
||||
}
|
||||
|
||||
private String getFromManifest(String key) {
|
||||
try {
|
||||
Enumeration<URL> resources = RunCommand.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
|
||||
while (resources.hasMoreElements()) {
|
||||
InputStream stream = resources.nextElement().openStream();
|
||||
Manifest manifest = new Manifest(stream);
|
||||
Attributes attributes = manifest.getMainAttributes();
|
||||
String mainClass = attributes.getValue("Main-Class");
|
||||
if (main.getClass().getName().equals(mainClass)) {
|
||||
String command = attributes.getValue("Main-Command");
|
||||
if (command != null) {
|
||||
stream.close();
|
||||
return command;
|
||||
try (InputStream stream = resources.nextElement().openStream()) {
|
||||
Manifest manifest = new Manifest(stream);
|
||||
Attributes attributes = manifest.getMainAttributes();
|
||||
String mainClass = attributes.getValue("Main-Class");
|
||||
if (main.getClass().getName().equals(mainClass)) {
|
||||
String value = attributes.getValue(key);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
stream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e.getMessage());
|
||||
@@ -442,26 +467,7 @@ public class VertxCommandLauncher extends UsageMessageFormatter {
|
||||
* @return the main verticle, {@code null} if not found.
|
||||
*/
|
||||
protected String getMainVerticle() {
|
||||
try {
|
||||
Enumeration<URL> resources = RunCommand.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
|
||||
while (resources.hasMoreElements()) {
|
||||
InputStream stream = resources.nextElement().openStream();
|
||||
Manifest manifest = new Manifest(stream);
|
||||
Attributes attributes = manifest.getMainAttributes();
|
||||
String mainClass = attributes.getValue("Main-Class");
|
||||
if (main != null && main.getClass().getName().equals(mainClass)) {
|
||||
String theMainVerticle = attributes.getValue("Main-Verticle");
|
||||
if (theMainVerticle != null) {
|
||||
stream.close();
|
||||
return theMainVerticle;
|
||||
}
|
||||
}
|
||||
stream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
return getFromManifest("Main-Verticle");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,6 @@ public class BareCommandFactory extends DefaultCommandFactory<BareCommand> {
|
||||
* Creates a new instance of {@link BareCommandFactory}.
|
||||
*/
|
||||
public BareCommandFactory() {
|
||||
super(BareCommand.class);
|
||||
super(BareCommand.class, BareCommand::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ public abstract class ClasspathHandler extends DefaultCommand {
|
||||
classloader = (classpath == null || classpath.isEmpty()) ?
|
||||
ClasspathHandler.class.getClassLoader() : createClassloader();
|
||||
Class<?> clazz = classloader.loadClass("io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer");
|
||||
return clazz.newInstance();
|
||||
return clazz.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to load or instantiate the isolated deployer", e);
|
||||
throw new IllegalStateException(e);
|
||||
@@ -156,6 +156,15 @@ public abstract class ClasspathHandler extends DefaultCommand {
|
||||
Thread.currentThread().setContextClassLoader(classloader);
|
||||
Method method = manager.getClass().getMethod("deploy", String.class, Vertx.class, DeploymentOptions.class,
|
||||
Handler.class);
|
||||
|
||||
if (executionContext.get("Default-Verticle-Factory") != null) {
|
||||
// there is a configured default
|
||||
if (verticle.indexOf(':') == -1) {
|
||||
// and the verticle is not using a explicit factory
|
||||
verticle = executionContext.get("Default-Verticle-Factory") + ":" + verticle;
|
||||
}
|
||||
}
|
||||
|
||||
method.invoke(manager, verticle, vertx, options, completionHandler);
|
||||
} catch (InvocationTargetException e) {
|
||||
log.error("Failed to deploy verticle " + verticle, e.getCause());
|
||||
|
||||
@@ -23,6 +23,6 @@ public class ListCommandFactory extends DefaultCommandFactory<ListCommand> {
|
||||
* Creates a new {@link ListCommandFactory}.
|
||||
*/
|
||||
public ListCommandFactory() {
|
||||
super(ListCommand.class);
|
||||
super(ListCommand.class, ListCommand::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ public class RunCommandFactory extends DefaultCommandFactory<RunCommand> {
|
||||
* Creates a new instance of {@link RunCommandFactory}.
|
||||
*/
|
||||
public RunCommandFactory() {
|
||||
super(RunCommand.class);
|
||||
super(RunCommand.class, RunCommand::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ public class StartCommandFactory extends DefaultCommandFactory<StartCommand> {
|
||||
* Creates a new instance of {@link StartCommandFactory}.
|
||||
*/
|
||||
public StartCommandFactory() {
|
||||
super(StartCommand.class);
|
||||
super(StartCommand.class, StartCommand::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ public class StopCommandFactory extends DefaultCommandFactory<StopCommand> {
|
||||
* Creates a new instance of {@link StopCommandFactory}.
|
||||
*/
|
||||
public StopCommandFactory() {
|
||||
super(StopCommand.class);
|
||||
super(StopCommand.class, StopCommand::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ public class VersionCommandFactory extends DefaultCommandFactory<VersionCommand>
|
||||
* Creates a new instance of {@link VersionCommandFactory}.
|
||||
*/
|
||||
public VersionCommandFactory() {
|
||||
super(VersionCommand.class);
|
||||
super(VersionCommand.class, VersionCommand::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ import io.vertx.core.cli.CommandLine;
|
||||
import io.vertx.core.cli.annotations.CLIConfigurator;
|
||||
import io.vertx.core.cli.impl.ReflectionUtils;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link CommandFactory}. This implementation defines the {@link CLI} from the
|
||||
* given {@link Command} implementation (by reading the annotation). Then, {@link Command} instance are
|
||||
@@ -26,14 +28,28 @@ import io.vertx.core.cli.impl.ReflectionUtils;
|
||||
public class DefaultCommandFactory<C extends Command> implements CommandFactory<C> {
|
||||
|
||||
private final Class<C> clazz;
|
||||
private final Supplier<C> supplier;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CommandFactory}.
|
||||
*
|
||||
* @param clazz the {@link Command} implementation
|
||||
* @deprecated Please use {@link #DefaultCommandFactory(Class, Supplier)}
|
||||
*/
|
||||
@Deprecated
|
||||
public DefaultCommandFactory(Class<C> clazz) {
|
||||
this(clazz, () -> ReflectionUtils.newInstance(clazz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link CommandFactory}.
|
||||
*
|
||||
* @param clazz the {@link Command} implementation
|
||||
* @param supplier the {@link Command} implementation
|
||||
*/
|
||||
public DefaultCommandFactory(Class<C> clazz, Supplier<C> supplier) {
|
||||
this.clazz = clazz;
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,9 +57,7 @@ public class DefaultCommandFactory<C extends Command> implements CommandFactory<
|
||||
*/
|
||||
@Override
|
||||
public C create(CommandLine cl) {
|
||||
C c = ReflectionUtils.newInstance(clazz);
|
||||
CLIConfigurator.inject(cl, c);
|
||||
return c;
|
||||
return supplier.get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,6 @@ import io.vertx.core.spi.launcher.DefaultCommandFactory;
|
||||
|
||||
public class ComplexCommandFactory extends DefaultCommandFactory<ComplexCommand> {
|
||||
public ComplexCommandFactory() {
|
||||
super(ComplexCommand.class);
|
||||
super(ComplexCommand.class, ComplexCommand::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import io.vertx.core.spi.launcher.DefaultCommandFactory;
|
||||
|
||||
public class GoodByeCommandFactory extends DefaultCommandFactory<GoodByeCommand> {
|
||||
public GoodByeCommandFactory() {
|
||||
super(GoodByeCommand.class);
|
||||
super(GoodByeCommand.class, GoodByeCommand::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2017 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
*/
|
||||
|
||||
package io.vertx.core.impl.launcher.commands;
|
||||
|
||||
import io.vertx.core.cli.CLIException;
|
||||
import io.vertx.core.cli.annotations.Description;
|
||||
import io.vertx.core.cli.annotations.Name;
|
||||
import io.vertx.core.cli.annotations.Option;
|
||||
import io.vertx.core.cli.annotations.Summary;
|
||||
import io.vertx.core.spi.launcher.DefaultCommand;
|
||||
|
||||
@Summary("A command saying hello.")
|
||||
@Description("A simple command to wish you a good day. Pass your name with `--name`")
|
||||
@Name(value = "hello", priority = 100)
|
||||
public class Hello2Command extends HelloCommand {
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2017 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
*/
|
||||
|
||||
package io.vertx.core.impl.launcher.commands;
|
||||
|
||||
import io.vertx.core.spi.launcher.DefaultCommandFactory;
|
||||
|
||||
|
||||
public class Hello2CommandFactory extends DefaultCommandFactory<Hello2Command> {
|
||||
|
||||
public Hello2CommandFactory() {
|
||||
super(Hello2Command.class, Hello2Command::new);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import io.vertx.core.spi.launcher.DefaultCommandFactory;
|
||||
public class HelloCommandFactory extends DefaultCommandFactory<HelloCommand> {
|
||||
|
||||
public HelloCommandFactory() {
|
||||
super(HelloCommand.class);
|
||||
super(HelloCommand.class, HelloCommand::new);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import io.vertx.core.spi.launcher.DefaultCommandFactory;
|
||||
public class HiddenCommandFactory extends DefaultCommandFactory<HiddenCommand> {
|
||||
|
||||
public HiddenCommandFactory() {
|
||||
super(HiddenCommand.class);
|
||||
super(HiddenCommand.class, HiddenCommand::new);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2017 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
*/
|
||||
|
||||
package io.vertx.core.impl.launcher.commands;
|
||||
|
||||
import io.vertx.core.spi.launcher.Command;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Test the priority check.
|
||||
*/
|
||||
public class PriorityCommandTest extends CommandTestBase {
|
||||
|
||||
private Command hello;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
super.setUp();
|
||||
// run the command
|
||||
cli.execute("hello", "-name", "priority 100");
|
||||
// it should be stored as an instance so we can inspect it...
|
||||
hello = cli.getExistingCommandInstance("hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHelloCommandIsOfTypeHello2() {
|
||||
// ensure that we get the right command, Hello2 is the command "hello" with higher priority
|
||||
assertThat(hello.getClass())
|
||||
.isEqualTo(Hello2Command.class);
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,6 @@
|
||||
io.vertx.core.impl.launcher.commands.HelloCommandFactory
|
||||
io.vertx.core.impl.launcher.commands.GoodByeCommandFactory
|
||||
io.vertx.core.impl.launcher.commands.HiddenCommandFactory
|
||||
io.vertx.core.impl.launcher.commands.ComplexCommandFactory
|
||||
io.vertx.core.impl.launcher.commands.ComplexCommandFactory
|
||||
# This command will have higher priority and override the previous one
|
||||
io.vertx.core.impl.launcher.commands.Hello2CommandFactory
|
||||
|
||||
Reference in New Issue
Block a user