/* * eXist Open Source Native XML Database * Copyright (C) 2001-2012 The eXist Project * http://exist-db.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * $Id$ */ package org.exist.client; import java.io.File; import java.net.URISyntaxException; import java.nio.file.Path; import java.util.*; import org.exist.xmldb.XmldbURI; import org.exist.xquery.util.URIUtils; import se.softhouse.jargo.*; import static org.exist.util.ArgumentUtil.*; import static se.softhouse.jargo.Arguments.*; /** * Command Line Options for the {@link InteractiveClient} * * @author Adam Retter <adam.retter@googlemail.com> * @author wessels */ public class CommandlineOptions { /* general arguments */ private static final Argument<?> helpArg = helpArgument("-h", "--help"); private static final Argument<Boolean> quietArg = optionArgument("-q", "--quiet") .description("be quiet. Just print errors.") .defaultValue(false) .build(); private static final Argument<Boolean> verboseArg = optionArgument("-v", "--verbose") .description("be verbose. Display progress information on put.") .defaultValue(false) .build(); private static final Argument<File> outputFileArg = fileArgument("-O", "--output") .description("write output of command into given file (use with -x, -g).") .build(); private static final Argument<Map<String, String>> optionArg = stringArgument("-o", "--option") .description("specify extra options: property=value. For available properties see client.properties.") .asKeyValuesWithKeyParser(StringParsers.stringParser()) .build(); /* database connection arguments */ private static final Argument<String> userArg = stringArgument("-u", "--user") .description("set username.") .defaultValue(null) .build(); private static final Argument<String> passwordArg = stringArgument("-P", "--password") .description("specify password.") .build(); private static final Argument<Boolean> useSslArg = optionArgument("-S", "--use-ssl") .description("Use SSL by default for remote connections") .defaultValue(false) .build(); private static final Argument<Boolean> embeddedArg = optionArgument("-l", "--local") .description("launch a local database instance. Otherwise client will connect to URI specified in client.properties.") .defaultValue(false) .build(); private static final Argument<File> embeddedConfigArg = fileArgument("-C", "--config") .description("specify alternate configuration file. Implies -l.") .build(); private static final Argument<Boolean> noEmbeddedModeArg = optionArgument("-N", "--no-embedded-mode") .description("do not make embedded mode available") .defaultValue(false) .build(); /* gui arguments */ private static final Argument<Boolean> noGuiArg = optionArgument("-s", "--no-gui") .description("don't start client with GUI. Just use the shell.") .defaultValue(false) .build(); private static final Argument<Boolean> guiQueryDialogArg = optionArgument("-Q", "--query") .description("directly open the query gui") .defaultValue(false) .build(); /* mk/rm/set collection arguments */ private static final Argument<String> mkColArg = stringArgument("-m", "--mkcol") .description("create a collection (and any missing parent collection). Implies -c.") .build(); private static final Argument<String> rmColArg = stringArgument("-R", "--rmcol") .description("remove entire collection") .build(); private static final Argument<String> setColArg = stringArgument("-c", "--collection") .description("set target collection.") .build(); /* put/get/rm document arguments */ private static final Argument<List<File>> parseDocsArg = fileArgument("-p", "--parse") .description("store files or directories given as extra args on command line.") .variableArity() .build(); private static final Argument<String> getDocArg = stringArgument("-g", "--get") .description("retrieve a document.") .build(); private static final Argument<String> rmDocArg = stringArgument("-r", "--remove") .description("remove a document.") .build(); /* query arguments */ public static final String XPATH_STDIN = "<<STDIN"; private static final Argument<String> xpathArg = stringArgument("-x", "--xpath") .description("execute XPath query given as argument. Without argument reads query from stdin.") .build(); private static final Argument<List<File>> loadQueriesArg = fileArgument("-F", "--file") .description("load queries from file and execute in random order.") .variableArity() .build(); private static final Argument<Integer> howManyResultsArg = integerArgument("-n", "--howmany") .description("max. number of query results to be displayed.") .build(); private static final Argument<File> traceQueriesArg = fileArgument("-T", "--trace") .description("log queries to the file specified by the argument (for debugging).") .build(); /* xupdate arguments */ private static final Argument<String> setDocArg = stringArgument("-f", "--resource") .description("specify a resource contained in the current collection. Use in conjunction with --xupdate to specify the resource to update.") .build(); private static final Argument<File> xupdateArg = fileArgument("-X", "--xupdate") .description("process XUpdate commands. Commands are read from the file specified in the argument.") .build(); /* reindex arguments */ private static final Argument<Boolean> reindexArg = optionArgument("-i", "--reindex") .description("reindex the collection specified in the collection argument --collection") .defaultValue(false) .build(); private static final Argument<Boolean> reindexRecurseDirsArg = optionArgument("-d", "--recurse-dirs") .description("recurse into subdirectories during index?") .defaultValue(false) .build(); private static Optional<XmldbURI> optUri(final ParsedArguments parsedArguments, final Argument<String> argument) throws URISyntaxException { final Optional<String> uriStr = getOpt(parsedArguments, argument); if (uriStr.isPresent()) { return Optional.of(URIUtils.encodeXmldbUriFor(uriStr.get())); } else { return Optional.empty(); } } public static CommandlineOptions parse(final String[] args) throws ArgumentException, URISyntaxException { final ParsedArguments arguments = CommandLineParser .withArguments(userArg, passwordArg, useSslArg, embeddedArg, embeddedConfigArg, noEmbeddedModeArg) .andArguments(noGuiArg, guiQueryDialogArg) .andArguments(mkColArg, rmColArg, setColArg) .andArguments(parseDocsArg, getDocArg, rmDocArg) .andArguments(xpathArg, loadQueriesArg, howManyResultsArg, traceQueriesArg) .andArguments(setDocArg, xupdateArg) .andArguments(reindexArg, reindexRecurseDirsArg) .andArguments(helpArg, quietArg, verboseArg, outputFileArg, optionArg) .parse(args); final boolean quiet = getBool(arguments, quietArg); final boolean verbose = getBool(arguments, verboseArg); final Optional<Path> outputFile = getPathOpt(arguments, outputFileArg); final Map<String, String> options = arguments.get(optionArg); final Optional<String> username = getOpt(arguments, userArg); final Optional<String> password = getOpt(arguments, passwordArg); final boolean useSSL = getBool(arguments, useSslArg); final boolean embedded = getBool(arguments, embeddedArg); final Optional<Path> embeddedConfig = getPathOpt(arguments, embeddedConfigArg); final boolean noEmbeddedMode = getBool(arguments, noEmbeddedModeArg); final boolean startGUI = !getBool(arguments, noGuiArg); final boolean openQueryGUI = getBool(arguments, guiQueryDialogArg); final Optional<XmldbURI> mkCol = optUri(arguments, mkColArg); final Optional<XmldbURI> rmCol = optUri(arguments, rmColArg); final Optional<XmldbURI> setCol = optUri(arguments, setColArg); final List<Path> parseDocs = getPathsOpt(arguments, parseDocsArg); final Optional<XmldbURI> getDoc = optUri(arguments, getDocArg); final Optional<String> rmDoc = getOpt(arguments, rmDocArg); final Optional<String> maybeXpath = getOpt(arguments, xpathArg); final Optional<String> xpath; if(maybeXpath.isPresent()) { if(maybeXpath.get().isEmpty()) { xpath = Optional.of(XPATH_STDIN); } else { xpath = maybeXpath; } } else { xpath = Optional.empty(); } final List<Path> queryFiles = getPathsOpt(arguments, loadQueriesArg); final Optional<Integer> howManyResults = getOpt(arguments, howManyResultsArg); final Optional<Path> traceQueriesFile = getPathOpt(arguments, traceQueriesArg); final Optional<String> setDoc = getOpt(arguments, setDocArg); final Optional<Path> xupdateFile = getPathOpt(arguments, xupdateArg); final boolean reindex = getBool(arguments, reindexArg); final boolean reindexRecurse = getBool(arguments, reindexRecurseDirsArg); return new CommandlineOptions( quiet, verbose, outputFile, options, username, password, useSSL, embedded, embeddedConfig, noEmbeddedMode, startGUI, openQueryGUI, mkCol, rmCol, setCol, parseDocs, getDoc, rmDoc, xpath, queryFiles, howManyResults, traceQueriesFile, setDoc, xupdateFile, reindex, reindexRecurse ); } public CommandlineOptions(boolean quiet, boolean verbose, Optional<Path> outputFile, Map<String, String> options, Optional<String> username, Optional<String> password, boolean useSSL, boolean embedded, Optional<Path> embeddedConfig, boolean noEmbeddedMode, boolean startGUI, boolean openQueryGUI, Optional<XmldbURI> mkCol, Optional<XmldbURI> rmCol, Optional<XmldbURI> setCol, List<Path> parseDocs, Optional<XmldbURI> getDoc, Optional<String> rmDoc, Optional<String> xpath, List<Path> queryFiles, Optional<Integer> howManyResults, Optional<Path> traceQueriesFile, Optional<String> setDoc, Optional<Path> xupdateFile, boolean reindex, boolean reindexRecurse) { this.quiet = quiet; this.verbose = verbose; this.outputFile = outputFile; this.options = options; this.username = username; this.password = password; this.useSSL = useSSL; this.embedded = embedded; this.embeddedConfig = embeddedConfig; this.noEmbeddedMode = noEmbeddedMode; this.startGUI = startGUI; this.openQueryGUI = openQueryGUI; this.mkCol = mkCol; this.rmCol = rmCol; this.setCol = setCol; this.parseDocs = parseDocs; this.getDoc = getDoc; this.rmDoc = rmDoc; this.xpath = xpath; this.queryFiles = queryFiles; this.howManyResults = howManyResults; this.traceQueriesFile = traceQueriesFile; this.setDoc = setDoc; this.xupdateFile = xupdateFile; this.reindex = reindex; this.reindexRecurse = reindexRecurse; } final boolean quiet; final boolean verbose; final Optional<Path> outputFile; final Map<String, String> options; final Optional<String> username; final Optional<String> password; final boolean useSSL; final boolean embedded; final Optional<Path> embeddedConfig; final boolean noEmbeddedMode; final boolean startGUI; final boolean openQueryGUI; final Optional<XmldbURI> mkCol; final Optional<XmldbURI> rmCol; final Optional<XmldbURI> setCol; final List<Path> parseDocs; final Optional<XmldbURI> getDoc; final Optional<String> rmDoc; final Optional<String> xpath; final List<Path> queryFiles; final Optional<Integer> howManyResults; final Optional<Path> traceQueriesFile; final Optional<String> setDoc; final Optional<Path> xupdateFile; final boolean reindex; final boolean reindexRecurse; }