All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oracle.kv.util.migrator.Main Maven / Gradle / Ivy

Go to download

NoSQL Database Server - supplies build and runtime support for the server (store) side of the Oracle NoSQL Database.

The newest version!
/*-
 * Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle NoSQL
 * Database made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle NoSQL Database for a copy of the license and
 * additional information.
 */

package oracle.kv.util.migrator;

import java.util.Set;

import oracle.kv.impl.util.CommandParser;
import oracle.kv.util.migrator.impl.FactoryBase;

/**
 * The main class of data migrator utility, supports 3 kinds of command lines:
 *
 * 1. Displays valid sources or sinks
 * Usage: java -jar KVHOME/lib/migrator.jar -sources
 * Usage: java -jar KVHOME/lib/migrator.jar -sinks
 *
 * 2. Migrates based on configuration file:
 * Usage: java -jar KVHOME/lib/migrator.jar -config  [-verbose]
 *
 * 3. Migrates from specified source to sink using command line:
 * Usage: java -jar KVHOME/lib/migrator.jar
 *      -source  -sink 
 *      <... other arguments ...>
 */
public class Main {

    private MigrateConfig config;
    private boolean verbose;

    public Main(String args[]) {
        MainCommandParser parser = new MainCommandParser(args);
        parser.parseArgs();

        if (parser.getListSources()) {
            listSourcesOrSinks(true, parser.getShowHidden());
        }
        if (parser.getListSinks()) {
            listSourcesOrSinks(false, parser.getShowHidden());
        }
        if (parser.getConfigFile() != null) {
            config = parseLoadConfig(parser.getConfigFile());
        } else {
            config = parseLoadConfig(parser.getSourceType(),
                                     parser.getSinkType(),
                                     parser);
        }
        verbose = parser.getVerbose();
    }

    public void run() {
        Migrator migrator = new Migrator(config, (verbose ? System.out : null));
        migrator.run();
    }

    private MigrateConfig parseLoadConfig(String configFile) {

        config = MigrateConfig.parseFromFile(configFile);

        String sourceType = config.getSource();
        DataSourceFactory sourceFac = Migrator.getSourceFactory(sourceType);
        DataSourceConfig sourceCfg = sourceFac.parseConfig(configFile);
        if (sourceCfg == null) {
            throw new IllegalArgumentException(
                "Fail to create configuration for source " + sourceType);
        }
        config.setSourceConfig(sourceCfg);

        String sinkType = config.getSink();
        DataSinkFactory sinkFac = Migrator.getSinkFactory(sinkType);
        DataSinkConfig sinkCfg = sinkFac.parseConfig(configFile);
        if (sinkCfg == null) {
            String msg = "Fail to create configuration for sink " + configFile;
            throw new IllegalArgumentException(msg);
        }
        config.setSinkConfig(sinkCfg);

        return config;
    }

    private MigrateConfig parseLoadConfig(String sourceType,
                                          String sinkType,
                                          MainCommandParser parser) {

        config = new MigrateConfig(sourceType, sinkType, false);

        DataSourceFactory srcFac = Migrator.getSourceFactory(sourceType);
        DataSinkFactory sinkFac = Migrator.getSinkFactory(sinkType);

        final String usageText = makeUsage(sourceType, sinkType);
        parser = new MainCommandParser(parser.getUnparsedArgs(), usageText);
        config.parseArgs(parser);
        config.setSourceConfig(srcFac.createConfig(parser));

        parser.setLastParse();
        config.setSinkConfig(sinkFac.createConfig(parser));
        return config;
    }

    public static void main(String args[]) {
        try {
            Main migrator = new Main(args);
            migrator.run();
        } catch (Exception ex) {
            exit(ExitCode.EXIT_FAILED, "Migrate failed. " + ex.getMessage());
        }
        exit(ExitCode.EXIT_OK, "Migrate complete.");
    }

    /**
     * Returns the command line for the specified source/sink pair.
     */
    public static String makeUsage(String source, String sink) {
        validateSourceSink(source, sink);

        StringBuilder sb = new StringBuilder();
        appendUsage(sb, source, sink);
        return sb.toString();
    }

    /**
     * Returns the command lines for the specified source.
     */
    public static String makeUsage(String source, boolean showHidden) {
        validateSource(source, showHidden);

        StringBuilder sb = new StringBuilder();
        for (String sink : Migrator.getSinkTypes(showHidden)) {
            try {
                validateSourceSink(source, sink);
            } catch (IllegalArgumentException iae) {
                /* Ignore invalid source/sink combination */
                continue;
            }
            if (sb.length() > 0) {
                sb.append("\n");
            }
            appendUsage(sb, source, sink);
        }
        return sb.toString();
    }

    private static void appendUsage(StringBuilder sb,
                                    String sourceType,
                                    String sinkType) {
        DataSourceFactory srcFac = Migrator.getSourceFactory(sourceType);
        DataSinkFactory sinkFac = Migrator.getSinkFactory(sinkType);
        sb.append("From ");
        sb.append(sourceType);
        sb.append(" to ");
        sb.append(sinkType);
        sb.append(":\n");
        sb.append(CommandParser.MIGRATOR_USAGE_PREFIX);
        sb.append("\n\t");
        sb.append(MainCommandParser.SOURCE_FLAG);
        sb.append(" ");
        sb.append(sourceType);
        sb.append(" ");
        sb.append(MainCommandParser.SINK_FLAG);
        sb.append(" ");
        sb.append(sinkType);
        sb.append("\n\t");
        sb.append(srcFac.getConfigCommandArgs());
        sb.append("\n\t");
        sb.append(sinkFac.getConfigCommandArgs());
        sb.append("\n\t");
        sb.append(MigrateConfig.getCommandArgs());
        sb.append("\n");
    }

    static void showUsage(String sourceType,
                          String sinkType,
                          boolean showHidden) {
        String usageText;
        if (sourceType != null) {
            if (sinkType != null) {
                usageText = makeUsage(sourceType, sinkType);
            } else {
                usageText = makeUsage(sourceType, showHidden);
            }
            usage(usageText, null);
        }
    }

    static void usage(String errorMsg) {
        usage(null, errorMsg);
    }

    static void usage(String usage, String errorMsg) {
        exit(ExitCode.EXIT_USAGE,
             ((errorMsg != null)? errorMsg + "\n\n" : "") +
             ((usage == null)? getCommandUsage() : usage));
    }

    private static void listSourcesOrSinks(boolean isSource,
                                           boolean showHidden) {

        Set types = isSource ? Migrator.getSourceTypes(showHidden) :
                                       Migrator.getSinkTypes(showHidden);

        StringBuilder sb = new StringBuilder("Valid ");
        sb.append(isSource ? "sources: " : "sinks: ");
        boolean first = true;
        for (String type : types) {
            if (first) {
                first = false;
            } else {
                sb.append(", ");
            }
            sb.append(type);
        }
        exit(ExitCode.EXIT_USAGE, sb.toString());
    }

    private static void exit(ExitCode exitCode, String errorMsg) {
        System.err.println(errorMsg);
        System.exit(exitCode.value());
    }

    static void validateSource(String sourceType, boolean showHidden) {
        Set srcTypes = Migrator.getSourceTypes(showHidden);
        if (!srcTypes.contains(sourceType)) {
            throw new IllegalArgumentException(
                "Invalid source: " + sourceType +
                ", valid sources: " + srcTypes);
        }
    }

    static void validateSourceSink(String sourceType, String sinkType) {

        DataSourceFactory srcFac = Migrator.getSourceFactory(sourceType);
        DataSinkFactory sinkFac = Migrator.getSinkFactory(sinkType);

        if (sourceType.equals(sinkType)) {
            throw new IllegalArgumentException(
                "Invalid Source/Sink combination, they are same type: " +
                sourceType);
        }

        /*
         * Dump a textual source to another textual sink seems not be
         * useful
         */
        if (srcFac instanceof FactoryBase && sinkFac instanceof FactoryBase) {
            if (((FactoryBase)srcFac).isTextual() &&
                ((FactoryBase)sinkFac).isTextual()) {
                throw new IllegalArgumentException(
                    "Invalid Source/Sink combination, both are textual type: " +
                    sourceType + ", " + sinkType);
            }
        }
    }

    static String getConfigFileUsage() {
        return "Migrates based on configuration file:\n" +
            CommandParser.MIGRATOR_USAGE_PREFIX +
            MainCommandParser.CONFIG_FLAG + "  " +
            CommandParser.optional(CommandParser.VERBOSE_FLAG);
    }

    /*
     * Usage: Usage: java -jar KVHOME/lib/migrator.jar 

    options must be one of:
     -sources -- lists valid migration source strings
     -sinks -- lists valid migration sink string
         -config  -- migrate based on the file configuration
         -source  -- migrate from the specified source. For additional usage
          of this option use:
         java -jar /migrator.jar -source  -help
    */

    private static final String COMMAND_USAGE =
        CommandParser.MIGRATOR_USAGE_PREFIX + "\n" +
        " must be one of:\n\t" +
        MainCommandParser.SOURCES_FLAG +
            " -- lists valid migration source type\n\t" +
        MainCommandParser.SINKS_FLAG +
            " -- lists valid migration sink type\n\t" +
        MainCommandParser.CONFIG_FLAG +
            "  -- migrate based on the file configuration\n\t" +
        MainCommandParser.SOURCE_FLAG +
            "  -- migrate from the specified source.\n\t" +
        "For additional usage of this option use:\n\t" +
        CommandParser.MIGRATOR_USAGE_PREFIX +
            MainCommandParser.SOURCE_FLAG + "  -help" ;

    static String getCommandUsage() {
        return COMMAND_USAGE;
    }

    /*
     * The possible return codes for the migrator utility, obeying the Unix
     * convention that a non-zero value is an abnormal termination.
     */
    public static enum ExitCode {

        EXIT_OK(0, "Operation completed"),
        EXIT_USAGE(100, "Usage error"),
        EXIT_FAILED(101, "Operation failed");

        /* A value that is a valid Unix return code, in the range of 0-127 */
        private final int returnCode;
        private final String description;

        ExitCode(int returnCode, String description) {
            this.returnCode = returnCode;
            this.description = description;
        }

        public int value(){
            return this.returnCode;
        }

        public String getDescription() {
            return description;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy