org.apache.ofbiz.base.start.StartupCommandUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ofbiz.base.start.StartupCommandUtil.java

Source

/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.ofbiz.base.start;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

/**
 * A utility class for processing OFBiz command line arguments
 * 
 * <p>
 * Defines OFBiz startup options called through main e.g. --load-data or --help
 * in addition to utility methods for parsing and handling these options
 * </p> 
 */
public final class StartupCommandUtil {

    /* 
     * Make sure of defining the same set of values in:
     * 
     * - The StartupOptions in the StartupOption enum
     * - The commons-cli options (e.g. HELP, START, etc ...)
     * - The getOfbizStartupOptions method
     * 
     * Keeping these items in sync means that OFBiz behaves correctly
     * while being decoupled from the commons-cli library and the only
     * place where commons-cli is used is in this class
     */

    public enum StartupOption {
        HELP("help"), LOAD_DATA("load-data"), PORTOFFSET("portoffset"), SHUTDOWN("shutdown"), START(
                "start"), STATUS("status"), TEST("test");

        private String name;

        private StartupOption(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }

    private static final Option HELP = Option.builder("?").longOpt(StartupOption.HELP.getName())
            .desc("Prints this help screen to the user").hasArg(false).build();
    private static final Option LOAD_DATA = Option.builder("l").longOpt(StartupOption.LOAD_DATA.getName())
            .desc("Creates tables/load data e.g:" + System.lineSeparator() + "-l readers=seed,demo,ext"
                    + System.lineSeparator() + "-l timeout=7200" + System.lineSeparator() + "-l delegator=default"
                    + System.lineSeparator() + "-l group=org.apache.ofbiz" + System.lineSeparator()
                    + "-l dir=directory/of/files" + System.lineSeparator() + "-l file=/tmp/dataload.xml")
            .numberOfArgs(2).valueSeparator('=').optionalArg(true).argName("key=value").build();
    private static final Option PORTOFFSET = Option.builder("o").longOpt(StartupOption.PORTOFFSET.getName())
            .desc("Offsets all default ports for OFBiz").hasArg().argName("offset").optionalArg(false).build();
    private static final Option SHUTDOWN = Option.builder("d").longOpt(StartupOption.SHUTDOWN.getName())
            .desc("Shutdown OFBiz").hasArg(false).build();
    private static final Option START = Option.builder("u").longOpt(StartupOption.START.getName())
            .desc("Start OFBiz").hasArg(false).build();
    private static final Option STATUS = Option.builder("s").longOpt(StartupOption.STATUS.getName())
            .desc("Gives the status of OFBiz").hasArg(false).build();
    private static final Option TEST = Option.builder("t").longOpt(StartupOption.TEST.getName())
            .desc("Runs the selected test or all if none selected e.g.: " + System.lineSeparator()
                    + "--test component=base --test case=somecase" + System.lineSeparator() + "or"
                    + System.lineSeparator() + "--test component=base --test suitename=xyz")
            .numberOfArgs(2).valueSeparator('=').optionalArg(true).argName("key=value").build();

    static final List<StartupCommand> parseOfbizCommands(final String[] args) throws StartupException {
        CommandLine commandLine = null;
        CommandLineParser parser = new DefaultParser();
        try {
            commandLine = parser.parse(StartupCommandUtil.getOfbizStartupOptions(), args);
        } catch (ParseException e) {
            throw new StartupException(e.getMessage());
        }
        validateAllCommandArguments(commandLine);
        return mapCommonsCliOptionsToStartupCommands(commandLine);
    }

    static final void printOfbizStartupHelp(final PrintStream printStream) {
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp(new PrintWriter(printStream, true), HelpFormatter.DEFAULT_WIDTH + 6,
                "ofbiz|ofbizDebug|ofbizBackground",
                System.lineSeparator() + "Executes OFBiz command e.g. start, shutdown, check status, etc",
                getOfbizStartupOptions(), HelpFormatter.DEFAULT_LEFT_PAD, HelpFormatter.DEFAULT_DESC_PAD,
                "note: Only one command can execute at a time. Portoffset may be appended." + System.lineSeparator()
                        + "Also a command must be invoked separately for each argument e.g."
                        + System.lineSeparator()
                        + "gradlew \"ofbiz --test component=somecomp --test case=somecase\"",
                true);
    }

    static final void highlightAndPrintErrorMessage(String errorMessage) {
        System.err.println("==============================================================================="
                + System.lineSeparator() + errorMessage + System.lineSeparator()
                + "===============================================================================");
    }

    private static final Options getOfbizStartupOptions() {
        OptionGroup ofbizCommandOptions = new OptionGroup();
        ofbizCommandOptions.addOption(HELP);
        ofbizCommandOptions.addOption(LOAD_DATA);
        ofbizCommandOptions.addOption(SHUTDOWN);
        ofbizCommandOptions.addOption(START);
        ofbizCommandOptions.addOption(STATUS);
        ofbizCommandOptions.addOption(TEST);

        Options options = new Options();
        options.addOptionGroup(ofbizCommandOptions);
        options.addOption(PORTOFFSET);
        return options;
    }

    private static final List<StartupCommand> mapCommonsCliOptionsToStartupCommands(final CommandLine commandLine) {
        Set<Option> uniqueOptions = new HashSet<Option>(Arrays.asList(commandLine.getOptions()));
        return uniqueOptions.stream()
                .map(option -> new StartupCommand.Builder(option.getLongOpt())
                        .properties(populateMapFromProperties(commandLine.getOptionProperties(option.getLongOpt())))
                        .build())
                .collect(Collectors.toList());
    }

    private static final Map<String, String> populateMapFromProperties(final Properties properties) {
        return properties.entrySet().stream().collect(Collectors.toMap(entry -> String.valueOf(entry.getKey()),
                entry -> String.valueOf(entry.getValue())));
    }

    private static final void validateAllCommandArguments(CommandLine commandLine) throws StartupException {
        // Make sure no extra options are passed
        if (!commandLine.getArgList().isEmpty()) {
            throw new StartupException("unrecognized options / properties: " + commandLine.getArgList());
        }
        // PORTOFFSET validation
        if (commandLine.hasOption(StartupOption.PORTOFFSET.getName())) {
            Properties optionProperties = commandLine.getOptionProperties(StartupOption.PORTOFFSET.getName());
            try {
                int portOffset = Integer.parseInt(optionProperties.keySet().iterator().next().toString());
                if (portOffset < 0) {
                    throw new StartupException("you can only pass positive integers to the option --"
                            + StartupOption.PORTOFFSET.getName());
                }
            } catch (NumberFormatException e) {
                throw new StartupException(
                        "you can only pass positive integers to the option --" + StartupOption.PORTOFFSET.getName(),
                        e);
            }
        }
    }
}