package ru.vyarus.dropwizard.orient.support; import com.google.common.collect.Lists; import com.orientechnologies.orient.console.OConsoleDatabaseApp; import io.dropwizard.Configuration; import io.dropwizard.cli.ConfiguredCommand; import io.dropwizard.setup.Bootstrap; import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Subparser; import ru.vyarus.dropwizard.orient.configuration.HasOrientServerConfiguration; import ru.vyarus.dropwizard.orient.configuration.OrientServerConfiguration; import java.io.File; import java.io.IOException; import java.util.List; /** * Command is launched in interactive mode if started without parameters: console config.yml. * <p>Also can be used to launch commands directly or external commands file. This time process will * exit right after commands execution.</p> * <p>To execute sql file: console config.yml commands.sql</p> * <p>To execute commands: console config.yml command1;command2</p> * <p>NOTE: server will not start when console command called, because dropwizard will not run managed objects this time * (only server command triggers managed objects lifecycle). But plocal connections still could be used. * Also, if server already started, then you can use remote connections.</p> * <a href="http://www.orientechnologies.com/docs/last/orientdb.wiki/Console-Commands.html"> * See orient console documentation</a> * * @param <T> configuration type * @see com.orientechnologies.orient.console.OConsoleDatabaseApp */ @SuppressWarnings("PMD.SystemPrintln") public class ConsoleCommand<T extends Configuration & HasOrientServerConfiguration> extends ConfiguredCommand<T> { public static final String COMMANDS_ARG = "commands"; private Class<T> configClass; /** * @param configClass configuration class */ public ConsoleCommand(final Class<T> configClass) { this(configClass, "console"); } /** * @param configClass configuration class * @param commandName command name to override default 'console' name */ public ConsoleCommand(final Class<T> configClass, final String commandName) { super(commandName, "Run orient db console"); this.configClass = configClass; } /** * {@inheritDoc} */ @Override protected Class<T> getConfigurationClass() { // configuration class is required, because real application configuration class is unreachable return configClass; } /** * {@inheritDoc} */ @Override public void configure(final Subparser subparser) { super.configure(subparser); subparser.addArgument(COMMANDS_ARG).nargs("*").help("orient console commands or commands file"); } /** * {@inheritDoc} */ @Override protected void run(final Bootstrap<T> bootstrap, final Namespace namespace, final T configuration) throws Exception { final OrientServerConfiguration conf = configuration.getOrientServerConfiguration(); final List<String> commands = namespace.get(COMMANDS_ARG); printHelp(conf, commands); OConsoleDatabaseApp.main(commands.toArray(new String[commands.size()])); } @SuppressWarnings("PMD.UselessParentheses") private void printHelp(final OrientServerConfiguration conf, final List<String> commands) { System.out.println("See details of command usage: " + "http://www.orientechnologies.com/docs/last/orientdb.wiki/Console-Commands.html"); if (conf == null) { return; } final boolean isInteractiveMode = commands.isEmpty(); final String dbFolder = (conf.getFilesPath() + "/databases/").replaceAll("//", "/"); final List<String> availableDatabases = getDatabases(dbFolder); // print help message if (isInteractiveMode && !availableDatabases.isEmpty()) { System.out.println("To connect database use one of the following commands:"); for (String db : availableDatabases) { if (conf.isStart()) { System.out.println(String.format("$ connect remote:localhost/%s root root", db)); } System.out.println(String.format("$ connect plocal:%s root root", cleanupDbPath(dbFolder, db))); } } } private List<String> getDatabases(final String dbFolder) { final List<String> availableDatabases = Lists.newArrayList(); final File file = new File(dbFolder); if (file.exists() && file.isDirectory()) { final File[] files = file.listFiles(); if (files != null) { for (File db : files) { if (db.isDirectory()) { availableDatabases.add(db.getName()); } } } } return availableDatabases; } @SuppressWarnings("PMD.EmptyCatchBlock") private String cleanupDbPath(final String basedir, final String name) { String res = basedir + name; try { res = new File(res).getCanonicalPath(); } catch (IOException ignored) { // ignore: in worse case badly formatted path will be shown } return res; } }