Skip to content
This repository has been archived by the owner on Nov 29, 2023. It is now read-only.

Commit

Permalink
Resolves GH-16: Switch off abandoned CLI parsing library to picocli
Browse files Browse the repository at this point in the history
Args4j is no longer being actively developed - switch to the current
widely-used library to continue receiving improvements and fixes
  • Loading branch information
romeara committed Jan 21, 2020
1 parent 165697f commit 612f54e
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 102 deletions.
1 change: 1 addition & 0 deletions CHANGE_LOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
### Changed
- Updated dependencies to latest bugfix release (gson, okhttp, commons-codec, slf4j, alloy)
- (GH-16) Switched from args4j CLI parsing to picocli, as args4j no longer seems actively maintained

## [0.2.1]
### Changed
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ repositories { mavenCentral() }
dependencies {
compileOnly 'com.google.code.findbugs:jsr305'

compile 'args4j:args4j'
compile 'com.google.code.gson:gson'
compile 'com.squareup.okhttp3:okhttp'
compile 'commons-codec:commons-codec'
compile 'info.picocli:picocli'
compile 'org.slf4j:slf4j-api'
compile 'org.starchartlabs.alloy:alloy-core'

Expand Down
4 changes: 2 additions & 2 deletions dependencies.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
# Entries are ordered alphabetically by group, then artifact
# Entries are in groups/blocks based on matching group IDs

args4j:args4j=2.33

com.google.code.findbugs:jsr305=3.0.2

com.google.code.gson:gson=2.8.6
Expand All @@ -13,6 +11,8 @@ com.squareup.okhttp3:okhttp=3.14.4

commons-codec:commons-codec=1.13

info.picocli:picocli=4.1.4

org.slf4j:slf4j-api=1.7.29
org.slf4j:slf4j-simple=1.7.29

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# General library settings
group=org.starchartlabs.lure
version=0.2.2-SNAPSHOT
version=0.3.0-SNAPSHOT

org.gradle.console=plain
org.gradle.warning.mode=all
Expand Down
84 changes: 4 additions & 80 deletions src/main/java/org/starchartlabs/lure/CommandLineInterface.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,9 @@
*/
package org.starchartlabs.lure;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.stream.Collectors;
import org.starchartlabs.lure.command.LureCommand;

import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.spi.SubCommand;
import org.kohsuke.args4j.spi.SubCommandHandler;
import org.kohsuke.args4j.spi.SubCommands;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.starchartlabs.lure.command.PostbinCommand;
import org.starchartlabs.lure.command.PushCommand;
import picocli.CommandLine;

/**
* Main entry point for command line calls to the application
Expand All @@ -41,70 +27,8 @@
*/
public class CommandLineInterface {

/** Logger reference to output information to the application log files */
private final Logger logger = LoggerFactory.getLogger(getClass());

@Argument(handler = SubCommandHandler.class)
@SubCommands({
@SubCommand(name = PushCommand.COMMAND_NAME, impl = PushCommand.class),
@SubCommand(name = PostbinCommand.COMMAND_NAME, impl = PostbinCommand.class),
})
private Runnable command;

public static void main(String[] args) {
new CommandLineInterface().run(args);
}

public void run(String[] args) {
CmdLineParser parser = new CmdLineParser(this);

try {
// parse the arguments.
parser.parseArgument(args);

if (command != null) {
command.run();
} else {
logger.error("Invalid command line arguments");
printUsage(parser);
}
} catch (CmdLineException e) {
logger.error("Invalid command line arguments", e);
printUsage(parser);
}
}

private void printUsage(CmdLineParser parser) {
Objects.requireNonNull(parser);

StringWriter usageWriter = new StringWriter();

// Print sub-command usages
Map<String, Object> subCommands = new HashMap<>();
subCommands.put(PushCommand.COMMAND_NAME, new PushCommand());
subCommands.put(PostbinCommand.COMMAND_NAME, new PostbinCommand());

String subCommandsList = subCommands.keySet().stream()
.collect(Collectors.joining(" | "));

usageWriter
.append("java " + getClass().getSimpleName() + " (" + subCommandsList + ") [options...] arguments...");
usageWriter.append('\n');
usageWriter.append('\n');

parser.printUsage(usageWriter, null);

for (Entry<String, Object> subCommand : subCommands.entrySet()) {
usageWriter.append(subCommand.getKey());
usageWriter.append('\n');

CmdLineParser subParser = new CmdLineParser(subCommand.getValue());
subParser.printUsage(usageWriter, null);
usageWriter.append('\n');
}

String usage = usageWriter.toString();
logger.error("\n{}", usage);
public static void main(String[] args) throws Exception {
new CommandLine(new LureCommand()).execute(args);
}

}
36 changes: 36 additions & 0 deletions src/main/java/org/starchartlabs/lure/command/LureCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2020 StarChart-Labs Contributors (https://github.com/StarChart-Labs)
*
* 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.starchartlabs.lure.command;

import picocli.CommandLine.Command;

/**
* Represents the lure command-set as a whole. This structure is used by the picocli library, as it assumes output may
* be things structured like "git", where there is a first command indicating the program, and second indicating the
* operation
*
* @author romeara
* @since 0.3.0
*/
@Command(mixinStandardHelpOptions = true, subcommands = { PostbinCommand.class, PushCommand.class })
public class LureCommand implements Runnable {

@Override
public void run() {
// This command has no behavior of its own, and serves to structure sub-commands
}

}
26 changes: 17 additions & 9 deletions src/main/java/org/starchartlabs/lure/command/PostbinCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

import javax.annotation.Nullable;

import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.starchartlabs.lure.model.postbin.PostbinCreateResponse;
Expand All @@ -39,6 +38,9 @@
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParentCommand;

/**
* Command line sub-command that will pull requests from PostBin and push it to a web URL following patterns defined for
Expand All @@ -47,6 +49,9 @@
* @author romeara
* @since 0.2.0
*/
@Command(
description = "Pipes a payloads from postb.in to an indicated web URL, mimicing the GitHub webook call pattern",
name = PostbinCommand.COMMAND_NAME, mixinStandardHelpOptions = true)
public class PostbinCommand implements Runnable {

public static final String COMMAND_NAME = "postbin";
Expand All @@ -63,20 +68,23 @@ public class PostbinCommand implements Runnable {

private final OkHttpClient httpClient = new OkHttpClient();

@Option(name = "-t", aliases = { "--target-url" }, required = true,
usage = "Specifies the server URL to POST the event to. Required")
@ParentCommand
private LureCommand lureCommand;

@Option(names = { "-t", "--target-url" }, required = true,
description = "Specifies the server URL to POST the event to. Required")
private String targetUrl;

@Option(name = "-b", aliases = { "--bin-id" }, required = false,
usage = "Specifies the Postbin bin ID to poll. If unspecified, a new bin is created")
@Option(names = { "-b", "--bin-id" }, required = false,
description = "Specifies the Postbin bin ID to poll. If unspecified, a new bin is created")
private String binId;

@Option(name = "-p", aliases = { "--poll-frequency" }, required = false,
usage = "Specifies the frequency in seconds to poll Postbin for new requests at, must be greater than 0. Defaults to 10 seconds")
@Option(names = { "-p", "--poll-frequency" }, required = false,
description = "Specifies the frequency in seconds to poll Postbin for new requests at, must be greater than 0. Defaults to 10 seconds")
private int pollFrequencySeconds = 10;

@Option(name = "-r", aliases = { "--postbin-root-url" }, required = false,
usage = "Specifies the root URL of Postbin to use. Defaults to https://postb.in/api")
@Option(names = { "-r", "--postbin-root-url" }, required = false,
description = "Specifies the root URL of Postbin to use. Defaults to https://postb.in/api")
private String rootUrl = "https://postb.in/api";

@Override
Expand Down
26 changes: 17 additions & 9 deletions src/main/java/org/starchartlabs/lure/command/PushCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@

import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -38,13 +37,19 @@
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParentCommand;

/**
* Command line sub-command that will push raw data to a web URL following patterns defined for GitHub webhook calls
*
* @author romeara
* @since 0.1.0
*/
@Command(
description = "Pushes a provided payload to an indicated web URL, mimicing the GitHub webook call pattern",
name = PushCommand.COMMAND_NAME, mixinStandardHelpOptions = true)
public class PushCommand implements Runnable {

public static final String COMMAND_NAME = "push";
Expand All @@ -63,21 +68,24 @@ public class PushCommand implements Runnable {
/** Logger reference to output information to the application log files */
private final Logger logger = LoggerFactory.getLogger(getClass());

@Option(name = "-t", aliases = { "--target-url" }, required = true,
usage = "Specifies the server URL to POST the event to. Required")
@ParentCommand
private LureCommand lureCommand;

@Option(names = { "-t", "--target-url" }, required = true,
description = "Specifies the server URL to POST the event to. Required")
private String targetUrl;

@Option(name = "-e", aliases = { "--event-name" }, required = true,
usage = "Specifies the GitHub event name to send as. Required")
@Option(names = { "-e", "--event-name" }, required = true,
description = "Specifies the GitHub event name to send as. Required")
private String eventName;

@Nullable
@Option(name = "-s", aliases = { "--secret" }, required = false,
usage = "Specifies the webhook secret to secure the event post with")
@Option(names = { "-s", "--secret" }, required = false,
description = "Specifies the webhook secret to secure the event post with")
private String webhookSecret;

@Option(name = "-c", aliases = { "--content" }, required = true,
usage = "Specifies the file containing the event content to send. Required")
@Option(names = { "-c", "--content" }, required = true,
description = "Specifies the file containing the event content to send. Required")
private File contentFile;

@Override
Expand Down

0 comments on commit 612f54e

Please sign in to comment.