org.conqat.lib.commons.options.CommandLineBase Maven / Gradle / Ivy
Show all versions of teamscale-lib-commons Show documentation
/*
* Copyright (c) CQSE GmbH
*
* 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 org.conqat.lib.commons.options;
import java.io.PrintWriter;
import java.util.function.Supplier;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.conqat.lib.commons.string.StringUtils;
/**
* Base class for running commandline programs.
*/
public abstract class CommandLineBase {
private CommandLine cmdLine;
/** Help option: print usage and exit. */
@Option(shortName = 'h', longName = "help", description = "print this usage message")
public void printUsageAndExit() {
cmdLine.printUsage(new PrintWriter(System.err));
System.exit(1);
}
/** Read the command line. */
protected void initFromCommandLine(String[] args) {
cmdLine = new CommandLine(new OptionRegistry(this));
try {
String[] leftOvers = cmdLine.parse(args);
handleLeftOvers(leftOvers);
} catch (OptionException e) {
abort("Incorrect options: " + e.getMessage());
}
}
/**
* Template methods for dealing with left overs (i.e. parameters that could not be parsed). The
* default implementation issues an error if leftovers are found.
*/
protected void handleLeftOvers(String[] leftOvers) {
if (leftOvers.length > 0) {
printError("Unsupported trailing options: " + StringUtils.concat(leftOvers, " "));
printUsageAndExit();
}
}
/** Aborts the JVM with the given message. */
protected static void abort(String message) {
printError(message);
System.exit(-1);
}
/** Executes the tool. */
protected abstract void run() throws E;
/** Initializes and executes the tool. */
protected static void execute(Supplier> constructor, String[] args)
throws E {
CommandLineBase tool = constructor.get();
tool.initFromCommandLine(args);
tool.run();
}
/** Exits this tool if the condition is false. */
protected static void exitIfFalse(boolean condition, String message) {
exitIfTrue(!condition, message);
}
/** Exits this tool if the condition is true. */
protected static void exitIfTrue(boolean condition, String message) {
if (condition) {
exitWithMessage(message, null);
}
}
/** Exits with the given message. */
protected static void exitWithMessage(String message) {
exitWithMessage(message, null);
}
/** Exits with the given message. */
protected static void exitWithMessage(String message, @Nullable Exception e) {
printError(message, e);
System.exit(1);
}
/**
* Prints the given {@code message} to the {@link System#out standard output stream}.
*
* Should be used in favor of {@link System#out
* System.out}{@link java.io.PrintStream#println(String) .println(...)} as this generates a new
* finding. Here, we can tolerate it once.
*
* @see #printError(String)
* @see #printError(String, Exception)
*/
protected static void printInfo(String message) {
System.out.println(message);
}
/**
* Prints the given {@code message} to the {@link System#err standard error output stream}.
*
* Should be used in favor of {@link System#err
* System.err}{@link java.io.PrintStream#println(String) .println(...)} as this generates a new
* finding. Here, we can tolerate it once.
*
* @see #printError(String, Exception)
* @see #printInfo(String)
*/
protected static void printError(String message) {
System.err.println(message);
}
/**
* Prints the given {@code message} and {@code exception} stack-trace to the {@link System#err
* standard error output stream}.
*
* Should be used in favor of {@link System#err
* System.err}{@link java.io.PrintStream#println(String) .println(...)} and
* {@link Exception#printStackTrace()} as this generates a new finding. Here, we can tolerate it
* once.
*
* @see #printError(String)
* @see #printInfo(String)
*/
protected static void printError(String message, Exception exception) {
printError(message);
if (exception != null) {
exception.printStackTrace();
}
}
}