io.warp10.worf.WorfCLI.java Source code

Java tutorial

Introduction

Here is the source code for io.warp10.worf.WorfCLI.java

Source

//
//   Copyright 2016  Cityzen Data
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//
package io.warp10.worf;

import com.google.common.base.Strings;
import io.warp10.Revision;
import org.apache.commons.cli.*;
import org.codehaus.jettison.json.JSONObject;

import java.io.File;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.UUID;

public class WorfCLI {
    public static boolean verbose = false;

    private Options options = new Options();

    public static String UUIDGEN_PRODUCER = "puidg";
    public static String UUIDGEN_OWNER = "ouidg";

    public static String P_UUID = "puid";
    public static String O_UUID = "ouid";

    public static String APPNAME = "a";

    private static String HELP = "h";
    private static String VERBOSE = "v";
    private static String VERSION = "version";
    private static String INTERACTIVE = "i";
    private static String OUTPUT = "o";
    private static String TOKEN = "t";
    private static String TTL = "ttl";
    private static String KEYSTORE = "ks";

    public WorfCLI() {
        options.addOption(new Option(KEYSTORE, "keystore", true,
                "configuration file for generating tokens inside templates"));
        options.addOption(new Option(OUTPUT, "output", true, "output configuration destination file"));
        options.addOption(new Option(TOKEN, "tokens", false, "generate read/write tokens"));
        options.addOption(new Option("f", "format", false, "output tokens format. (default JSON)"));

        OptionGroup groupProducerUID = new OptionGroup();
        groupProducerUID.addOption(new Option(UUIDGEN_PRODUCER, "producer-uuid-gen", false,
                "creates a new universally unique identifier for the producer"));
        groupProducerUID.addOption(new Option(P_UUID, "producer-uuid", true, "data producer uuid"));

        OptionGroup groupOwnerUID = new OptionGroup();
        groupOwnerUID.addOption(new Option(UUIDGEN_OWNER, "owner-uuid-gen", false,
                "creates a new universally unique identifier for the owner"));
        groupOwnerUID
                .addOption(new Option(O_UUID, "owner-uuid", true, "data owner uuid (producer uuid by default)"));

        options.addOptionGroup(groupProducerUID);
        options.addOptionGroup(groupOwnerUID);

        options.addOption(new Option(APPNAME, "app-name", true,
                "token application name. Used by token option or @warp:writeToken@ template"));
        options.addOption(new Option(TTL, "ttl", true,
                "token time to live (ms). Used by token option or @warp:writeToken@ template"));

        options.addOption(HELP, "help", false, "show help.");
        options.addOption(VERBOSE, "verbose", false, "Verbose mode");
        options.addOption(VERSION, "version", false, "Print version number and return");
        options.addOption(INTERACTIVE, "interactive", false, "Interactive mode, all other options are ignored");
    }

    public int execute(String[] args) {
        try {
            CommandLineParser parser = new BasicParser();
            CommandLine cmd = parser.parse(options, args);

            String inputFile = null;
            boolean interactive = false;
            boolean token = false;
            String outputFile = null;
            String keyStoreFile = null;

            String producerUID = null;
            String ownerUID = null;
            String appName = null;
            long ttl = 0L;

            PrintWriter out = new PrintWriter(System.out);

            if (cmd.hasOption(HELP)) {
                help();
                return 0;
            }

            if (cmd.hasOption(VERSION)) {
                version(out);
                return 0;
            }

            if (cmd.hasOption(VERBOSE)) {
                verbose = true;
            }

            if (cmd.hasOption(INTERACTIVE)) {
                interactive = true;
            }

            if (cmd.hasOption(OUTPUT)) {
                outputFile = cmd.getOptionValue(OUTPUT);
            }

            if (cmd.hasOption(KEYSTORE)) {
                keyStoreFile = cmd.getOptionValue(KEYSTORE);
            }

            if (cmd.hasOption(TOKEN)) {
                token = true;
                // PRODUCER UUID OPTION (mandatory)
                // --------------------------------------------------------------------
                if (cmd.hasOption(UUIDGEN_PRODUCER)) {
                    producerUID = UUID.randomUUID().toString();
                } else if (cmd.hasOption(P_UUID)) {
                    producerUID = cmd.getOptionValue(P_UUID);
                    UUID.fromString(producerUID);
                }

                // OWNER UUID OPTION (mandatory)
                // --------------------------------------------------------------------
                if (cmd.hasOption(UUIDGEN_OWNER)) {
                    ownerUID = UUID.randomUUID().toString();
                } else if (cmd.hasOption(O_UUID)) {
                    ownerUID = cmd.getOptionValue(O_UUID);
                    UUID.fromString(ownerUID);
                } else {
                    ownerUID = producerUID;
                }

                if (cmd.hasOption(APPNAME)) {
                    appName = cmd.getOptionValue(APPNAME);
                }

                if (cmd.hasOption(TTL)) {
                    ttl = Long.parseLong(cmd.getOptionValue(TTL));
                    long ttlMax = Long.MAX_VALUE - System.currentTimeMillis();

                    if (ttl >= ttlMax) {
                        throw new WorfException("TTL can not be upper than " + ttlMax + " ms");
                    }

                } else {
                    throw new WorfException("The option 'ttl' is missing ");
                }
            }

            // get the input file name
            switch (cmd.getArgs().length) {
            case 0:
                throw new WorfException("Config or template file missing.");

            case 1:
                inputFile = cmd.getArgs()[0];
                break;

            default:
                throw new WorfException("Too many arguments, only one config or template file expected.");
            }

            // load the interactive mode
            if (interactive) {
                return runInteractive(inputFile);
            }

            Properties config = Worf.readConfig(inputFile, out);

            //
            // TEMPLATE CONFIGURATION
            //
            if (WorfTemplate.isTemplate(config)) {

                // load keystore if needed
                WorfKeyMaster templateKeyMaster = null;
                if (!Strings.isNullOrEmpty(keyStoreFile)) {
                    // read config
                    Properties keyStoreConfig = Worf.readConfig(keyStoreFile, out);
                    // load key master
                    templateKeyMaster = new WorfKeyMaster(keyStoreConfig);

                    if (!templateKeyMaster.loadKeyStore()) {
                        throw new WorfException("Template Keystore not loaded");
                    }
                }

                WorfTemplate tpl = new WorfTemplate(config, inputFile);

                // GENERATE CRYPTO KEYS
                for (String cryptoKey : tpl.getCryptoKeys()) {
                    String keySize = tpl.generateCryptoKey(cryptoKey);
                    if (keySize != null) {
                        out.println(keySize + " bits secured key for " + cryptoKey + "  generated");
                    } else {
                        throw new WorfException("Unable to generate " + cryptoKey + ", template error");
                    }
                }

                // read defaults
                if (token) {
                    Properties defaultProperties = Worf.readDefault(inputFile, out);
                    appName = Worf.getDefault(defaultProperties, out, appName, APPNAME);
                    producerUID = Worf.getDefault(defaultProperties, out, producerUID, P_UUID);
                    ownerUID = Worf.getDefault(defaultProperties, out, ownerUID, O_UUID);
                }
                // GENERATE TOKENS
                for (String tokenKey : tpl.getTokenKeys()) {
                    if (!token) {
                        throw new WorfException("Unable to generate template tokens missing -t option");
                    }
                    if (templateKeyMaster == null) {
                        throw new WorfException("Unable to generate template tokens missing -ks option");
                    }

                    String tokenIdent = tpl.generateTokenKey(tokenKey, appName, ownerUID, producerUID, ttl,
                            templateKeyMaster);
                    out.println("Token generated key=" + tokenKey + "  ident=" + tokenIdent);
                }

                // GET INTERACTIVE CONFIGURATION
                if (tpl.getFieldsStack().size() > 0) {
                    throw new WorfException("Unable the update template, you are not in interactive mode");
                }

                // save the template
                if (Strings.isNullOrEmpty(outputFile)) {
                    Path inputConfigurationPath = Paths.get(inputFile);
                    String outputFileName = inputConfigurationPath.getFileName().toString();
                    outputFileName = outputFileName.replace("template", "conf");

                    StringBuilder sb = new StringBuilder();
                    sb.append(inputConfigurationPath.getParent().toString());
                    if (!inputConfigurationPath.endsWith(File.separator)) {
                        sb.append(File.separator);
                    }
                    sb.append(outputFileName);

                    outputFile = sb.toString();
                }
                tpl.saveConfig(outputFile);
                out.println("Warp configuration saved (" + outputFile + ")");
                out.flush();
                inputFile = outputFile;

                // Keystore is given as input
                //end of the job
                if (!Strings.isNullOrEmpty(keyStoreFile)) {
                    out.println("Warp configuration file used for tokens generation in templates");
                    out.println("For generate tokens, reload Worf without 'ks' option");
                    out.flush();
                    System.exit(0);
                }
            }

            //
            // GENERATE TOKEN
            //
            if (token) {
                // read config
                config = Worf.readConfig(inputFile, out);
                // load key master
                WorfKeyMaster keyMaster = new WorfKeyMaster(config);

                if (!keyMaster.loadKeyStore()) {
                    throw new WorfException("Keystore not loaded");
                }

                Properties defaultProperties = Worf.readDefault(inputFile, out);
                appName = Worf.getDefault(defaultProperties, out, appName, APPNAME);
                producerUID = Worf.getDefault(defaultProperties, out, producerUID, P_UUID);
                ownerUID = Worf.getDefault(defaultProperties, out, ownerUID, O_UUID);

                // save default
                if (defaultProperties == null) {
                    Worf.saveDefault(inputFile, appName, producerUID, ownerUID);
                }

                // deliver token
                String readToken = keyMaster.deliverReadToken(appName, producerUID, ownerUID, ttl);
                String writeToken = keyMaster.deliverWriteToken(appName, producerUID, ownerUID, ttl);

                // write outputformat
                JSONObject jsonOutput = new JSONObject();
                JSONObject jsonToken = new JSONObject();
                jsonToken.put("token", readToken);
                jsonToken.put("tokenIdent", keyMaster.getTokenIdent(readToken));
                jsonToken.put("ttl", ttl);
                jsonToken.put("application", appName);
                jsonToken.put("owner", ownerUID);
                jsonToken.put("producer", producerUID);

                jsonOutput.put("read", jsonToken);

                jsonToken = new JSONObject();
                jsonToken.put("token", writeToken);
                jsonToken.put("tokenIdent", keyMaster.getTokenIdent(writeToken));
                jsonToken.put("ttl", ttl);
                jsonToken.put("application", appName);
                jsonToken.put("owner", ownerUID);
                jsonToken.put("producer", producerUID);

                jsonOutput.put("write", jsonToken);

                System.out.println(jsonOutput.toString());
            }

        } catch (Exception we) {
            if (verbose) {
                we.printStackTrace();
            } else {
                System.out.println(we.getMessage() + "\n");
            }
            help();
            return -1;
        }
        return 0;
    }

    private static int runInteractive(String warp10Configuration) throws WorfException {
        WorfInteractive worfInteractive = new WorfInteractive();
        PrintWriter out = worfInteractive.getPrintWriter();

        // read warp10 configuration
        out.println("Reading warp10 configuration " + warp10Configuration);
        Properties config = Worf.readConfig(warp10Configuration, out);

        if (config == null) {
            out.println("Unable to read warp10 configuration.");
            out.flush();
            return -1;
        }

        if (WorfTemplate.isTemplate(config)) {
            warp10Configuration = worfInteractive.runTemplate(config, warp10Configuration);
            // reload config
            config = Worf.readConfig(warp10Configuration, out);
        }
        // get Default values
        Properties worfConfig = Worf.readDefault(warp10Configuration, out);
        worfInteractive.run(config, worfConfig);

        return 0;
    }

    private void help() {
        // This prints out some help
        HelpFormatter formater = new HelpFormatter();

        String header = "DESCRIPTION";
        String footer = " \n \nCOPYRIGHT\nCopyright  2016 Cityzen Data.\n Licensed under the Apache License, Version 2.0 (the \"License\")\n"
                + "you may not use this file except in compliance with the License.\n"
                + "You may obtain a copy of the License at\n" + "http://www.apache.org/licenses/LICENSE-2.0";

        formater.printHelp("worf [OPTION] SOURCE_CONFIG [-o OUTPUT_CONFIG]", header, options, footer, false);
        System.exit(0);
    }

    private void version(PrintWriter out) {
        out.println("Warp 10 revision " + Revision.REVISION);
        System.exit(0);
    }
}