net.sourceforge.jencrypt.CommandLineHelper.java Source code

Java tutorial

Introduction

Here is the source code for net.sourceforge.jencrypt.CommandLineHelper.java

Source

/*******************************************************************************
 * Copyright (c) 2013 "Ivo van Kamp"
 *
 * jEncrypt is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package net.sourceforge.jencrypt;

import java.io.File;
import java.io.IOException;
import java.util.Comparator;
import javax.crypto.Cipher;

import org.apache.commons.cli.*;

/**
 * This class contains methods to parse and fetch all jEncrypt commandline
 * options with the Apache CLI library.
 */
final class CommandLineHelper {

    /* Array of 3 -enc or -dec arguments */
    private String[] cipherOptions;

    /* Full path to configuration file or relative to user.dir */
    private String configFileString;

    /* Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE */
    private int cipherMode;

    /* Full path to key file or relative to user.dir */
    private String passwordString;

    /* Source file to decrypt or folder to encrypt */
    private String sourceFileOrFolder;
    private String targetPath;

    // Order and list of options
    private final String orderOfOptions = "edpi";

    CommandLineHelper(String[] args) throws ParseException {

        // Build the Apache CLI options and parse commandline arguments
        CommandLine commandLine = parseCommandline(args, getOptions(orderOfOptions));

        // Check command line options and store them in class variables
        getCommandlineOptions(commandLine);
    }

    /**
     * Build the Apache CLI Options collection based on the given string of
     * short opts.
     * 
     * @param selectOptions
     *            String of first characters of commandline options.
     * @return
     */
    private Options getOptions(String selectOptions) {

        Options options = new Options();

        Option newOption = null;

        // Walk through string of short opts and build CLI Options collection
        for (char s : selectOptions.toCharArray()) {
            switch (s) {
            case 'e':
                newOption = new Option("e", "enc", true, "[File or folder to encrypt] [Destination file]");
                newOption.setArgs(3);
                break;
            case 'd':
                newOption = new Option("d", "dec", true, "[File to decrypt] [Destination folder]");
                newOption.setArgs(3);
                break;
            case 'i':
                newOption = new Option("i", "ini", false, "[Configuration file]");
                newOption.setArgs(1);
                break;
            case 'p':
                newOption = new Option("p", "pwd", false, "[Password to use for en-/decryption]");
                newOption.setArgs(1);
                break;
            }
            if (newOption != null) {
                newOption.setArgName("");
                options.addOption(newOption);
            }
        }
        return options;
    }

    public String getTargetFolder() {
        return targetPath;
    }

    public String getSourceFileOrFolder() {
        return sourceFileOrFolder;
    }

    public String getPassword() {
        return passwordString;
    }

    public String getConfigFileString() {
        return configFileString;
    }

    public int getCipherMode() {
        return cipherMode;
    }

    /**
     * Formatter for printing the help text describing command line options. The
     * options are ordered as they appear in indexOfOptions.
     * 
     * @param indexOfOptions
     * @return
     */
    private HelpFormatter getHelpFormatter(final String indexOfOptions) {
        HelpFormatter helpFormatter = new HelpFormatter();
        helpFormatter.setOptionComparator(new Comparator<Option>() {
            public int compare(Option o1, Option o2) {
                return indexOfOptions.indexOf(o1.getOpt()) - indexOfOptions.indexOf(o2.getOpt());
            }
        });
        return helpFormatter;
    }

    /**
     * Parse the arguments according to the specified options
     * 
     * @param args
     * @param options
     * @return
     * @throws ParseException
     */
    private CommandLine parseCommandline(String[] args, Options options) throws ParseException {

        CommandLine commandLine = null;
        CommandLineParser parser = new GnuParser();

        try {
            // parse the command-line arguments
            commandLine = parser.parse(options, args);
        } catch (ParseException exp) {
            throw new ParseException("Parsing failed. Reason: " + exp.getMessage());
        }
        return commandLine;
    }

    /**
     * Print the help information for the options that have their short opt
     * letter appearing in listAndOrderOfOptions and print the options in order
     * of appearance.
     * 
     * @param listAndOrderOfOptions
     */
    public void printHelp(final String listAndOrderOfOptions) {
        Options options = getOptions(listAndOrderOfOptions);
        getHelpFormatter(listAndOrderOfOptions).printHelp("jencrypt", options);
    }

    /**
     * Print help information
     */
    public void printHelp() {
        // If the configuration file has already been specified
        // then don't print the ini option.
        if (getConfigFileString() != null) {
            printHelp(orderOfOptions.replace('i', ' '));
        } else
            printHelp(orderOfOptions);
    }

    /**
     * Check and store jEncrypt command line options
     * 
     * @param commandLine
     */
    private void getCommandlineOptions(CommandLine commandLine) {

        // Read and check command-line options
        String[] cipherOptionsEnc = commandLine.getOptionValues("enc");
        String[] cipherOptionsDec = commandLine.getOptionValues("dec");

        // Only encrypt or decrypt not both at the same time
        if (cipherOptionsEnc != null ^ cipherOptionsDec != null) {

            // Options -enc takes 2 arguments and -dec takes 1 or 2 arguments
            if (cipherOptionsEnc != null && cipherOptionsEnc.length == 2) {
                cipherMode = Cipher.ENCRYPT_MODE;
                cipherOptions = cipherOptionsEnc;
            } else if (cipherOptionsDec != null && (cipherOptionsDec.length < 3)) {
                cipherMode = Cipher.DECRYPT_MODE;

                // If no second argument was given assume current directory
                if (cipherOptionsDec.length == 1) {
                    cipherOptions = new String[] { cipherOptionsDec[0], "." };
                } else {
                    cipherOptions = cipherOptionsDec;
                }
            }

            if (cipherOptions != null) {
                sourceFileOrFolder = cipherOptions[0];
                targetPath = cipherOptions[1];
            }
        }
        configFileString = commandLine.getOptionValue("ini");
        passwordString = commandLine.getOptionValue("pwd");
    }

    /**
     * Check if the decryption destination directory, base directory and key
     * file exists.
     * 
     * @throws IOException
     */
    public boolean isValid() throws IOException {

        // Cipheroptions contains -end or -dec
        if (cipherOptions != null && configFileString != null && passwordString != null) {

            File source = new File(sourceFileOrFolder);

            if (this.getCipherMode() == Cipher.DECRYPT_MODE) {

                if (targetPath == "") {
                    targetPath = System.getProperty("user.dir");
                }
                File target = new File(targetPath);

                if (!source.exists()) {
                    throw new IOException("Source archive '" + sourceFileOrFolder + "' does not exist.");
                } else if (!source.isFile()) {
                    throw new IOException("Source archive '" + sourceFileOrFolder + "' is not a file");
                }

                if (!target.exists() || !target.canWrite()) {
                    throw new IOException("Destination '" + target.getName() + "' not found or access denied");
                }

            }

            if (this.getCipherMode() == Cipher.ENCRYPT_MODE) {

                File targetFile = new File(targetPath);

                if (targetFile.isDirectory()) {
                    throw new IOException("Destination '" + targetFile.getName() + "' is not a file");
                } else if (targetFile.exists()) {
                    throw new IOException("File '" + targetFile.getName() + "' already exists");
                } else {
                    try {
                        targetFile.createNewFile();
                    } catch (IOException e) {
                        throw new SecurityException("Can't create file '" + targetPath + "': " + e.getMessage());
                    } finally {
                        targetFile.delete();
                    }
                }
                if (!source.exists() || !source.canRead()) {
                    throw new IOException(
                            "Folder to encrypt '" + source.getName() + "' not found or access denied");
                }
            }

            return true;
        }
        return false;
    }
}