| /******************************************************************************* |
| * 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); |
| } |
| } |
| } |
| } |