package com.wouterbreukink.onedrive; import com.google.api.client.util.Sets; import org.apache.commons.cli.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Set; public class CommandLineOpts { private static final Logger log = LogManager.getLogger(Main.class.getName()); private static final Options optionsToParse = buildOptions(); private static final CommandLineOpts opts = new CommandLineOpts(); private boolean isInitialised; // Mandatory arguments private Direction direction; private String localPath; private String remotePath; // Optional arguments private boolean help = false; private boolean useHash = false; private int threads = 5; private int tries = 3; private boolean version = false; private boolean recursive = false; private int maxSizeKb = 0; private Path keyFile = Paths.get("onedrive.key"); private boolean dryRun = false; private String logFile = null; private int splitAfter = 5; private Set<String> ignored = null; private boolean authorise = false; public static CommandLineOpts getCommandLineOpts() { if (!opts.isInitialised) { throw new IllegalStateException("The command line options have not been initialised"); } return opts; } public static void initialise(String[] args) throws ParseException { CommandLineParser parser = new DefaultParser(); CommandLine line = parser.parse(optionsToParse, args); for (Option opt : line.getOptions()) { log.debug(String.format("Parsing command line option -%s, value = %s ", opt.getLongOpt() != null ? "-" + opt.getLongOpt() : opt.getOpt(), opt.getValue())); } opts.help = line.hasOption("help"); opts.useHash = line.hasOption("hash-compare"); opts.version = line.hasOption("version"); opts.recursive = line.hasOption("recursive"); opts.dryRun = line.hasOption("dry-run"); opts.authorise = line.hasOption("authorise"); if (line.hasOption("local")) { opts.localPath = line.getOptionValue("local"); } if (line.hasOption("remote")) { opts.remotePath = line.getOptionValue("remote"); } if (line.hasOption("direction")) { String chosen = line.getOptionValue("direction").toLowerCase(); if (!chosen.equals("up") && !chosen.equals("down")) { throw new ParseException("Direction must be one of up or down"); } opts.direction = Direction.valueOf(chosen.toUpperCase()); } if (line.hasOption("threads")) { opts.threads = Integer.parseInt(line.getOptionValue("threads")); } if (line.hasOption("tries")) { opts.tries = Integer.parseInt(line.getOptionValue("tries")); } if (line.hasOption("max-size")) { opts.maxSizeKb = Integer.parseInt(line.getOptionValue("max-size")); } if (line.hasOption("keyfile")) { opts.keyFile = Paths.get(line.getOptionValue("keyfile")); } if (line.hasOption("logfile")) { opts.logFile = line.getOptionValue("logfile"); } if (line.hasOption("split-after")) { opts.splitAfter = Integer.parseInt(line.getOptionValue("split-after")); if (opts.splitAfter > 60) { throw new ParseException("maximum permissible value for split-after is 60"); } } if (line.hasOption("ignore")) { Path ignoreFile = Paths.get(line.getOptionValue("ignore")); if (!Files.exists(ignoreFile)) { throw new ParseException("specified ignore file does not exist"); } try { opts.ignored = Sets.newHashSet(); opts.ignored.addAll(Files.readAllLines(ignoreFile, Charset.defaultCharset())); } catch (IOException e) { throw new ParseException(e.getMessage()); } } opts.isInitialised = true; } private static Options buildOptions() { Option authorise = Option.builder("a") .longOpt("authorise") .desc("generate authorisation url") .build(); Option hash = Option.builder("c") .longOpt("hash-compare") .desc("always compare files by hash") .build(); Option direction = Option.builder() .longOpt("direction") .hasArg() .argName("up|down") .desc("direction of synchronisation.") .build(); Option help = Option.builder("h") .longOpt("help") .desc("print this message") .build(); Option ignore = Option.builder("i") .longOpt("ignore") .hasArg() .argName("ignore_file") .desc("ignore entry file") .build(); Option keyFile = Option.builder("k") .longOpt("keyfile") .hasArg() .argName("file") .desc("key file to use") .build(); Option logLevel = Option.builder("L") .longOpt("log-level") .hasArg() .argName("level (1-7)") .desc("controls the verbosity of logging") .build(); Option localPath = Option.builder() .longOpt("local") .hasArg() .argName("path") .desc("the local path") .build(); Option logFile = Option.builder() .longOpt("logfile") .hasArg() .argName("file") .desc("log to file") .build(); Option maxSize = Option.builder("M") .longOpt("max-size") .hasArg() .argName("size_in_KB") .desc("only process files smaller than <size> KB") .build(); Option dryRun = Option.builder("n") .longOpt("dry-run") .desc("only do a dry run without making changes") .build(); Option recursive = Option.builder("r") .longOpt("recursive") .desc("recurse into directories") .build(); Option remotePath = Option.builder() .longOpt("remote") .hasArg() .argName("path") .desc("the remote path on OneDrive") .build(); Option splitAfter = Option.builder("s") .longOpt("split-after") .hasArg() .argName("size_in_MB") .desc("use multi-part upload for big files") .build(); Option threads = Option.builder("t") .longOpt("threads") .hasArg() .argName("count") .desc("number of threads to use") .build(); Option version = Option.builder("v") .longOpt("version") .desc("print the version information and exit") .build(); Option retries = Option.builder("y") .longOpt("tries") .hasArg() .argName("count") .desc("try each service request <count> times") .build(); return new Options() .addOption(authorise) .addOption(hash) .addOption(direction) .addOption(help) .addOption(ignore) .addOption(keyFile) .addOption(logLevel) .addOption(localPath) .addOption(logFile) .addOption(maxSize) .addOption(dryRun) .addOption(recursive) .addOption(remotePath) .addOption(splitAfter) .addOption(threads) .addOption(version) .addOption(retries); } public static void printHelp() { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("onedrive-java-syncer", optionsToParse); } public Direction getDirection() { return direction; } public String getLocalPath() { return localPath; } public String getRemotePath() { return remotePath; } public boolean help() { return help; } public int getThreads() { return threads; } public boolean useHash() { return useHash; } public int getTries() { return tries; } public boolean version() { return version; } public boolean isRecursive() { return recursive; } public int getMaxSizeKb() { return maxSizeKb; } public Path getKeyFile() { return keyFile; } public boolean isDryRun() { return dryRun; } public String getLogFile() { return logFile; } public int getSplitAfter() { return splitAfter; } public Set<String> getIgnored() { return ignored; } public boolean isAuthorise() { return authorise; } public enum Direction { UP, DOWN } }