/**
* Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.seed.cli.internal;
import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
import io.nuun.kernel.api.Kernel;
import io.nuun.kernel.api.config.KernelConfiguration;
import org.seedstack.seed.SeedException;
import org.seedstack.seed.cli.CliConfig;
import org.seedstack.seed.cli.CommandLineHandler;
import org.seedstack.seed.cli.spi.CliContext;
import org.seedstack.seed.core.Seed;
import org.seedstack.seed.spi.SeedLauncher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.util.Arrays;
import java.util.concurrent.Callable;
/**
* This class executes {@link CommandLineHandler}s found in the classpath.
*/
public class CliLauncher implements SeedLauncher {
private static final Logger LOGGER = LoggerFactory.getLogger(CliLauncher.class);
@Override
public void launch(String[] args) throws Exception {
int returnCode = execute(args);
LOGGER.info("CLI command finished with return code {}", returnCode);
System.exit(returnCode);
}
@Override
public void shutdown() throws Exception {
// nothing to do here
}
/**
* Execute a Seed CLI command (implemented by a {@link CommandLineHandler}.
*
* @param args the command line arguments. First argument is the name of the CLI command. Subsequent arguments are
* passed to the CLI command.
* @return the return code of the CLI command.
* @throws Exception when the CLI command fails to complete.
*/
public static int execute(String[] args) throws Exception {
CliConfig cliConfig = Seed.baseConfiguration().get(CliConfig.class);
Callable<Integer> callable;
String[] effectiveArgs;
if (cliConfig.hasDefaultCommand()) {
LOGGER.debug("Executing default CLI command " + cliConfig.getDefaultCommand());
callable = new SeedCallable(cliConfig.getDefaultCommand());
effectiveArgs = args;
} else {
if (args == null || args.length == 0 || args[0].isEmpty()) {
throw SeedException.createNew(CliErrorCode.NO_COMMAND_SPECIFIED);
}
callable = new SeedCallable(args[0]);
effectiveArgs = Arrays.copyOfRange(args, 1, args.length);
}
Kernel kernel = null;
try {
kernel = Seed.createKernel(new CliContext(effectiveArgs), null, true);
kernel.objectGraph().as(Injector.class).injectMembers(callable);
return callable.call();
} finally {
Seed.disposeKernel(kernel);
}
}
/**
* Method to execute a callable as a CLI application.
*
* @param args the command line arguments.
* @param callable the callable to execute
* @return the return code of the callable
* @throws Exception when the CLI command fails to complete.
*/
public static int execute(String[] args, Callable<Integer> callable) throws Exception {
Kernel kernel = Seed.createKernel(new CliContext(args), null, true);
try {
kernel.objectGraph().as(Injector.class).injectMembers(callable);
return callable.call();
} finally {
Seed.disposeKernel(kernel);
}
}
/**
* Method to execute a callable as a CLI application.
*
* @param args the command line arguments.
* @param callable the callable to execute
* @param kernelConfiguration a kernel configuration to use for the CLI application.
* @return the return code of the callable
* @throws Exception when the CLI command fails to complete.
*/
public static int execute(String[] args, Callable<Integer> callable, KernelConfiguration kernelConfiguration) throws Exception {
Kernel kernel = Seed.createKernel(new CliContext(args), kernelConfiguration, true);
try {
kernel.objectGraph().as(Injector.class).injectMembers(callable);
return callable.call();
} finally {
Seed.disposeKernel(kernel);
}
}
public static class SeedCallable implements Callable<Integer> {
private final String cliCommand;
@Inject
private Injector injector;
public SeedCallable(String cliCommand) {
this.cliCommand = cliCommand;
}
@Override
public Integer call() throws Exception {
try {
CommandLineHandler commandLineHandler = injector.getInstance(Key.get(CommandLineHandler.class, Names.named(cliCommand)));
LOGGER.info("Executing CLI command {}, handled by {}", cliCommand, commandLineHandler.getClass().getCanonicalName());
return commandLineHandler.call();
} catch (ConfigurationException e) {
throw SeedException.wrap(e, CliErrorCode.COMMAND_LINE_HANDLER_NOT_FOUND).put("commandLineHandler", cliCommand);
}
}
}
}