Package com.atolsystems.atolutilities

Source Code of com.atolsystems.atolutilities.aCat$FileListArgHandler

/*
*/
/**
*
* @author atol systems
*/

package com.atolsystems.atolutilities;

import com.atolsystems.atolutilities.CommandLine.Arg;
import com.atolsystems.atolutilities.CommandLine.ArgDef;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;
import javax.swing.filechooser.FileNameExtensionFilter;


public class aCat {
    static private final String DSTFILE_PATH_PREFERENCE_KEY = "com.atolsystems.atolutilities.aCat.dstFilePath";
    static private final String INPUTFILE_PATH_PREFERENCE_KEY = "com.atolsystems.atolutilities.aCat.inputFilePath";

    /**
     * An utility to concatenate several files into one
     * @param args
     */
    public static void main(String[] args){
        aCat u=new aCat(args);
    }

    public static void showHelp(CommandLine cl){
        java.util.ResourceBundle bundle1 = java.util.ResourceBundle.getBundle("com/atolsystems/atolutilities/resources/BuildNumber");
        System.out.println("\n\naCat v0.3 ("+"build "+bundle1.getString("build.number")+"), atol systems, 2011");
        System.out.println("Utility to concatenate several files into one, with various optional codecs");
        System.out.println("This program is currently run by the JVM from:");
        System.out.println("\t"+System.getProperty("java.home"));
        System.out.println("\nCommand line usage:");
        System.out.println(cl.help());
        System.out.println();
    }

    File dstFile;
    File tmpOutFile;
    boolean append;
    boolean internalAppend;
    boolean outHex;
    boolean inHex;
    boolean out64;
    boolean in64;
    boolean askOutKey;
    boolean askInKey;
    String outKey;
    String inKey;
    public aCat(String[] args) {
        try {
            CommandLine cl=new CommandLine();
            HelpArgHandler helpArgHandler=new HelpArgHandler();
            cl.addArgDef(helpArgHandler.argDef);
            GuiArgHandler guiArgHandler=new GuiArgHandler();
            cl.addArgDef(guiArgHandler.argDef);
            DstArgHandler setDstArgHandler=new DstArgHandler();
            cl.addArgDef(setDstArgHandler.argDef);
            OutHexArgHandler outHexArgHandler=new OutHexArgHandler();
            cl.addArgDef(outHexArgHandler.argDef);
            InHexArgHandler inHexArgHandler=new InHexArgHandler();
            cl.addArgDef(inHexArgHandler.argDef);
            Out64ArgHandler out64ArgHandler=new Out64ArgHandler();
            cl.addArgDef(out64ArgHandler.argDef);
            In64ArgHandler in64ArgHandler=new In64ArgHandler();
            cl.addArgDef(in64ArgHandler.argDef);
            OutKeyArgHandler outKeyArgHandler=new OutKeyArgHandler();
            cl.addArgDef(outKeyArgHandler.argDef);
            InKeyArgHandler inKeyArgHandler=new InKeyArgHandler();
            cl.addArgDef(inKeyArgHandler.argDef);
            AppendOnArgHandler appendOnArgHandler=new AppendOnArgHandler();
            cl.addArgDef(appendOnArgHandler.argDef);
            AppendOffArgHandler appendOffArgHandler=new AppendOffArgHandler();
            cl.addArgDef(appendOffArgHandler.argDef);
            AddArgHandler addArgHandler=new AddArgHandler();
            cl.addArgDef(addArgHandler.argDef);
            FileListArgHandler fileListArgHandler=new FileListArgHandler();
            cl.addArgDef(fileListArgHandler.argDef);

            if(0==args.length){
                FileNameExtensionFilter filter = new FileNameExtensionFilter("aCat arg files", "aCat");
                cl.askForArgFile(filter, true, true, true);
            }else
                cl.addNewArgs(args);
            if(cl.isEmpty()){
                showHelp(cl);
            }else{
                cl.processArgs();
            }
            if(null!=tmpOutFile)
                commitToOutputFile();
        } catch(ExitException e){
            System.out.println(e.getMessage());
        } catch (StopRequestFromUserException e) {
        } catch (IOException ex) {
            Logger.getLogger(CommandLine.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    class GuiArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="gui";
        final public ArgDef argDef=new ArgDef(mark, this);
        public String help() {
            return  "gui\n"+
                    "   Start graphical user interface mode";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            if(null==dstFile){
                try {
                    dstFile = AFileChooser.askForFile(null, true, "Choose destination file or 'Cancel' to exit", DSTFILE_PATH_PREFERENCE_KEY, true, false, true);
                    if(null==dstFile)
                        throw new StopRequestFromUserException();
                } catch (IOException ex) {
                    Logger.getLogger(aCat.class.getName()).log(Level.SEVERE, null, ex);
                }
                if(dstFile.exists()){
                    String actions[]={"append to file","overwrite file"};
                    String s = (String) JOptionPane.showInputDialog(
                        null,
                        "Choose an action or 'Cancel' to exit.",
                        "Selected file exist",
                        JOptionPane.PLAIN_MESSAGE,
                        null,
                        actions,
                        actions[0]);
                    if(null==s)
                        throw new StopRequestFromUserException();
                    if(s.equals(actions[0]))
                        internalAppend=true;
                    else
                        internalAppend=false;
                }
            }
            while(true){
                File[] input=null;
                try {
                    input = AFileChooser.askForFiles(null, true, "Choose an input file to append or 'Cancel' to exit", INPUTFILE_PATH_PREFERENCE_KEY, true, true, false, false);
                } catch (IOException ex) {
                    Logger.getLogger(aCat.class.getName()).log(Level.SEVERE, null, ex);
                }
                if(null==input)
                    break;
                for(int i=0;i<input.length;i++){
                    processInputFile(input[i]);
                    internalAppend=true;
                }
            }
            return true;
        }
    }
    class HelpArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="help";
        final public ArgDef argDef=new ArgDef(mark, this);
        public String help() {
            return  "help\n"+
                    "   Show this help";
        }

        public boolean processArg(Arg arg, CommandLine cl) {
            showHelp(cl);
            return true;
        }
    }
   
    class AppendOnArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="appendOn";
        final public ArgDef argDef=new ArgDef(mark, this);
        public String help() {
            return  "appendOn\n"+
                    "   Enable \"append\" mode: concatenated files are appended to destination file";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            append=true;
            internalAppend=append;
            return true;
        }
    }
    class AppendOffArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="appendOff";
        final public ArgDef argDef=new ArgDef(mark, this);
        public String help() {
            return  "appendOff\n"+
                    "   Disable \"append\" mode: concatenated files replace the destination file";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            append=false;
            internalAppend=append;
            return true;
        }
    }
    class OutHexArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="outHex";
        final public ArgDef argDef=new ArgDef(mark, this);
        public String help() {
            return  "outHex\n"+
                    "   Output an intel-hex file.";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            outHex=true;
            return true;
        }
    }
    class InHexArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="inHex";
        final public ArgDef argDef=new ArgDef(mark, this);
        public String help() {
            return  "inHex\n"+
                    "   Read input files as intel-hex files, offset and unspecified area are discarded.";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            inHex=true;
            return true;
        }
    }
    class Out64ArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="out64";
        final public ArgDef argDef=new ArgDef(mark, this);
        public String help() {
            return  "out64\n"+
                    "   Use base64 encoding for output file.";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            out64=true;
            return true;
        }
    }
    class In64ArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="in64";
        final public ArgDef argDef=new ArgDef(mark, this);
        public String help() {
            return  "in64\n"+
                    "   Use base64 encoding for input files.";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            in64=true;
            return true;
        }
    }
    class OutKeyArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="outKey";
        final public ArgDef argDef=new ArgDef(mark, this);
        public String help() {
            return  "outKey\n"+
                    "   Ask for a password to generate an AES encryption key to encrypt the output file.";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            askOutKey=true;
            return true;
        }
    }
    class InKeyArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="inKey";
        final public ArgDef argDef=new ArgDef(mark, this);
        public String help() {
            return  "inKey\n"+
                    "   Ask for a password to generate a decryption key to decrypt the input files.";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            askInKey=true;
            return true;
        }
    }
    class DstArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="dst:";
        final public ArgDef argDef=new ArgDef(mark, this);

        public String help() {
            return  "dst:[file]\n"+
                    "   Set destination file. If file is omitted, a dialog box ask for it";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            if(null!=dstFile) commitToOutputFile();
            dstFile=arg.getOptionalFile(mark, null, "Select destination file", DSTFILE_PATH_PREFERENCE_KEY, true);
            try {
                tmpOutFile = File.createTempFile("aCat", "aCatTmp");
            } catch (IOException ex) {
                throw new RuntimeException("Cannot create temp file.",ex);
            }
            internalAppend=append;
            if(null==dstFile) throw new RuntimeException("Cannot find file '"+arg.getSingleFileName(mark)+"'");
            return true;
        }
    }
    class AddArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="add:";
        final public ArgDef argDef=new ArgDef(mark, this);
        ArrayList<File> files=new ArrayList<File>();
        int iFiles=0;
        public String help() {
            return  "add:[file]\n"+
                    "   Append a file. If file is omitted, a dialog box ask for it";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            try {
                File file=files.get(iFiles);
                iFiles++;
                internalAppend=true;
                if(null!=file)//if user pressed "cancel" for an optional file, file==null here
                    processInputFile(file);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
            return true;
        }

        @Override
        public boolean inspectArg(Arg arg, CommandLine cl) {
            File toAdd=arg.getOptionalFile(mark, null, "Add a file to concatenate", INPUTFILE_PATH_PREFERENCE_KEY, false);
            //if(null==toAdd) throw new ExitException("Cannot find file '"+arg.getSingleFileName(mark)+"'");
            files.add(toAdd);
            return true;
        }
    }
    class FileListArgHandler extends SimpleArgHandler implements SelfDocumented{
        final public String mark="fileList:";
        final public ArgDef argDef=new ArgDef(mark, this);
        ArrayList<ArrayList<File>> files=new ArrayList<ArrayList<File>>();
        int iFiles=0;
        public String help() {
            return  "fileList:[file]\n"+
                    "   Add a file list: a file which contain one file name per line\n"+
                    "   Each file listed is concatenated to the destination file\n"+
                    "   To include a file list with a file list, start its line with \"<\"\n"+
                    "   If file is omitted, a dialog box ask for it\n";
        }
        public boolean processArg(Arg arg, CommandLine cl) {
            for(File file:files.get(iFiles)){
                processInputFile(file);
                internalAppend=true;
            }
            iFiles++;
            return true;
        }

        HashSet<String> fileListSet=new HashSet<String>();
        void processFileList(File fileListFile) throws FileNotFoundException, IOException{
            String line;
            File refDir=fileListFile.getParentFile();
            fileListSet.add(fileListFile.getCanonicalPath());
            BufferedReader in = new BufferedReader(new FileReader(fileListFile));
            line=in.readLine().trim();
            while(null!=line){
                if(line.startsWith("<")){
                    fileListFile=AFileUtilities.newFile(line.substring(1));
                    if(fileListSet.contains(fileListFile.getCanonicalPath()))
                        throw new InvalidCommandLineException("Circular reference in file list '"+fileListFile.getCanonicalPath()+"'");
                    processFileList(fileListFile);
                }else if (line.startsWith("//") || line.isEmpty()) {
                    //do nothing
                } else if (line.startsWith("/*")) {
                    int open = 1;
                    while(null!=line){
                        line=in.readLine().trim();
                        if (line.startsWith("/*")) {
                            open++;
                        } else if (line.startsWith("*/")) {
                            open--;
                        }
                        if (0 == open) {
                            break;
                        }
                    }
                    if (0 != open) {
                        throw new InvalidCommandLineException("Unterminated multiline comment found in list file '"+fileListFile.getCanonicalPath()+"'");
                    }
                } else{
                    //File toAdd=new File(refDir,line);
                    File toAdd=AFileUtilities.newFile(refDir,line);
                    files.get(files.size()-1).add(toAdd);
                }
                line=in.readLine();
            }
            in.close();
        }
        @Override
        public boolean inspectArg(Arg arg, CommandLine cl) {
            File fileListFile=arg.getOptionalFile(mark, null, "Choose a \"file list\" file", INPUTFILE_PATH_PREFERENCE_KEY, false);
            try {
                fileListSet.clear();
                ArrayList<File> newFileList=new ArrayList<File>();
                files.add(newFileList);
                if(null!=fileListFile)
                    processFileList(fileListFile);
            } catch (FileNotFoundException ex) {
                Logger.getLogger(aCat.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(aCat.class.getName()).log(Level.SEVERE, null, ex);
            }
           
            return true;
        }
    }
    void processInputFile(File inputFile){
        try {
            AFileUtilities.copyFile(tmpOutFile, inputFile, internalAppend);
        } catch (Throwable ex) {
            throw new RuntimeException(ex);
        }
    }
    private void commitToOutputFile(){
        try {
            if (null == dstFile) {
                if (null == tmpOutFile) {
                    return; //nothing to do
                }
                throw new RuntimeException("Ouptut file not set.");
            }

            //File tmpFilePostProcess=tmpOutFile;
            File tmpFilePostProcess=File.createTempFile("aCat", "aCatTmp");
            File tmpOutFileBu=tmpOutFile;
            //not the fastest way, should open the input do all transformation using streams...
            if(in64){
                AFileUtilities.copyFile(tmpFilePostProcess, tmpOutFile, false, false, true);
                tmpOutFile=tmpFilePostProcess;
                tmpFilePostProcess=tmpOutFileBu;
                tmpOutFileBu=tmpOutFile;
            }
            if(inHex){
                IntelHexFileReader.hex2Bin(tmpFilePostProcess, tmpOutFile, false);
                tmpOutFile=tmpFilePostProcess;
                tmpFilePostProcess=tmpOutFileBu;
                tmpOutFileBu=tmpOutFile;
            }
            if(askInKey){
                byte [] key=askKey();
                AFileUtilities.copyFile(tmpFilePostProcess, tmpOutFile, false, key, false);
                Arrays.fill(key,(byte)0);
                tmpOutFile=tmpFilePostProcess;
                tmpFilePostProcess=tmpOutFileBu;
                tmpOutFileBu=tmpOutFile;
            }
            if(askOutKey){
                byte [] key=askKey();
                AFileUtilities.copyFile(tmpFilePostProcess, tmpOutFile, false, key, true);
                Arrays.fill(key,(byte)0);
                tmpOutFile=tmpFilePostProcess;
                tmpFilePostProcess=tmpOutFileBu;
                tmpOutFileBu=tmpOutFile;
            }
            if(outHex){
                IntelHexFileWriter.bin2Hex(tmpFilePostProcess, tmpOutFile, false, 8);
                tmpOutFile=tmpFilePostProcess;
                tmpFilePostProcess=tmpOutFileBu;
                tmpOutFileBu=tmpOutFile;
            }
            if(out64){
                AFileUtilities.copyFile(tmpFilePostProcess, tmpOutFile, false, true, false);
                tmpOutFile=tmpFilePostProcess;
                tmpFilePostProcess=tmpOutFileBu;
                tmpOutFileBu=tmpOutFile;
            }
            AFileUtilities.copyFile(dstFile, tmpOutFile, append);
            tmpOutFile.delete();
            tmpOutFile = null;
            tmpFilePostProcess.delete();
            tmpFilePostProcess=null;
            dstFile = null;
        } catch (Throwable ex) {
            throw new RuntimeException(ex);
        }
    }
    private byte[] askKey(){
        JPasswordField password = new JPasswordField();
        JCheckBox restrictTo128Bits = new JCheckBox("Restrict key generation to 128 bits");
        final JComponent[] inputs = new JComponent[] {
                        new JLabel("Password"),
                        password,
                        restrictTo128Bits
        };
        JOptionPane.showMessageDialog(null, inputs, "Password", JOptionPane.PLAIN_MESSAGE);
        int keySize=(restrictTo128Bits.isSelected()) ? 16 : 32;
        return stringToAesKey(password.getPassword(), keySize);
    }
    private byte[] stringToAesKey(char[] password, int keySize){
        byte [] passwordTrailerBytes=new byte[32];//add 32 null bytes to make sure the resulting key can reach 256 bits
        byte [] passwordBytes = new byte[password.length+passwordTrailerBytes.length];
        System.arraycopy(passwordTrailerBytes, 0, passwordBytes, password.length, passwordTrailerBytes.length);
        for(int i=0;i<password.length;i++){
            passwordBytes[i]=(byte) password[i];
        }
        byte [] key=new byte[16];
        byte[] extendedKey;
        try {
            extendedKey = AES.performAES(key, passwordBytes, true);
        } catch (InvalidKeyException ex) {
            throw new RuntimeException(ex);
        }

        byte[] output = new byte[keySize];
        for(int i=0;i<extendedKey.length;i++)
            output[i%keySize]^=extendedKey[i];

        Arrays.fill(password,'0');
        Arrays.fill(passwordBytes,(byte)0);
        Arrays.fill(extendedKey,(byte)0);

        //System.out.println(AStringUtilities.bytesToHex(output));
        return output;
    }
}
TOP

Related Classes of com.atolsystems.atolutilities.aCat$FileListArgHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.