Skip to content

Commit dcc0e83

Browse files
authored
Merge pull request #572 from ancho/feature/picocli-integration
switch to picocli
2 parents df55d33 + 96156b0 commit dcc0e83

File tree

13 files changed

+176
-143
lines changed

13 files changed

+176
-143
lines changed

gradle.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ pebbleVersion = 3.1.5
2828
slf4jVersion = 1.7.30
2929
snakeYamlVersion = 1.28
3030
thymeleafVersion = 3.0.12.RELEASE
31+
picocli = 4.6.1
32+
3133

3234
# testing dependencies
3335
junit4Version = 4.13.2

jbake-core/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ dependencies {
3030

3131
// cli specific dependencies
3232
implementation "org.eclipse.jetty:jetty-server:$jettyServerVersion", optional
33-
implementation "args4j:args4j:$args4jVersion", optional
33+
implementation "info.picocli:picocli:$picocli", optional
3434
}
3535

3636
processResources {

jbake-core/src/main/java/org/jbake/app/ContentStore.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.orientechnologies.orient.core.sql.OCommandSQL;
3737
import com.orientechnologies.orient.core.sql.executor.OResultSet;
3838
import com.orientechnologies.orient.core.sql.query.OSQLSynchQuery;
39+
import org.jbake.launcher.SystemExit;
3940
import org.jbake.model.DocumentAttributes;
4041
import org.jbake.model.DocumentTypes;
4142
import org.slf4j.Logger;
@@ -212,7 +213,7 @@ public ODocument mergeDocument(Map<String, ? extends Object> incomingDocMap) {
212213
activateOnCurrentThread();
213214
List<ODocument> results = db.command(new OSQLSynchQuery<ODocument>(sql)).execute(sourceUri);
214215
if (results.isEmpty()) {
215-
throw new JBakeException("No document with sourceUri '" + sourceUri + "'.");
216+
throw new JBakeException(SystemExit.ERROR, "No document with sourceUri '" + sourceUri + "'.");
216217
}
217218

218219
// Update it from the given map.
Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.jbake.app;
22

3+
import org.jbake.launcher.SystemExit;
4+
35
/**
46
* This runtime exception is thrown by JBake API to indicate an processing
57
* error.
@@ -9,18 +11,26 @@
911
public class JBakeException extends RuntimeException {
1012
private static final long serialVersionUID = 1L;
1113

14+
final private SystemExit exit;
15+
1216
/**
17+
*
1318
* @param message
1419
* The error message.
1520
* @param cause
1621
* The causing exception or <code>null</code> if no cause
1722
* available.
1823
*/
19-
public JBakeException(final String message, final Throwable cause) {
24+
public JBakeException(final SystemExit exit, final String message, final Throwable cause) {
2025
super(message, cause);
26+
this.exit = exit;
27+
}
28+
29+
public JBakeException(final SystemExit exit, final String message) {
30+
this(exit, message, null);
2131
}
2232

23-
public JBakeException(final String message) {
24-
this(message, null);
33+
public int getExit() {
34+
return exit.getStatus();
2535
}
2636
}

jbake-core/src/main/java/org/jbake/app/configuration/ConfigUtil.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@
55
import org.apache.commons.configuration.PropertiesConfiguration;
66
import org.apache.commons.configuration.SystemConfiguration;
77
import org.jbake.app.JBakeException;
8+
import org.jbake.launcher.SystemExit;
89
import org.slf4j.Logger;
910
import org.slf4j.LoggerFactory;
1011

1112
import java.io.File;
1213
import java.net.URL;
13-
import java.nio.file.Path;
14-
import java.nio.file.Paths;
15-
import java.nio.charset.Charset;
1614

1715
/**
1816
* Provides Configuration related functions.
@@ -29,10 +27,10 @@ public class ConfigUtil {
2927
private CompositeConfiguration load(File source) throws ConfigurationException {
3028

3129
if (!source.exists()) {
32-
throw new JBakeException("The given source folder '" + source.getAbsolutePath() + "' does not exist.");
30+
throw new JBakeException(SystemExit.CONFIGURATION_ERROR, "The given source folder '" + source.getAbsolutePath() + "' does not exist.");
3331
}
3432
if (!source.isDirectory()) {
35-
throw new JBakeException("The given source folder is not a directory.");
33+
throw new JBakeException(SystemExit.CONFIGURATION_ERROR,"The given source folder is not a directory.");
3634
}
3735
CompositeConfiguration config = new CompositeConfiguration();
3836
config.setListDelimiter(',');

jbake-core/src/main/java/org/jbake/app/configuration/JBakeConfigurationInspector.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.jbake.app.FileUtil;
44
import org.jbake.app.JBakeException;
5+
import org.jbake.launcher.SystemExit;
56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
78

@@ -28,10 +29,10 @@ public void inspect() throws JBakeException {
2829
private void ensureSource() throws JBakeException {
2930
File source = configuration.getSourceFolder();
3031
if (!FileUtil.isExistingFolder(source)) {
31-
throw new JBakeException("Error: Source folder must exist: " + source.getAbsolutePath());
32+
throw new JBakeException(SystemExit.CONFIGURATION_ERROR, "Error: Source folder must exist: " + source.getAbsolutePath());
3233
}
3334
if (!configuration.getSourceFolder().canRead()) {
34-
throw new JBakeException("Error: Source folder is not readable: " + source.getAbsolutePath());
35+
throw new JBakeException(SystemExit.CONFIGURATION_ERROR, "Error: Source folder is not readable: " + source.getAbsolutePath());
3536
}
3637
}
3738

@@ -51,7 +52,7 @@ private void ensureDestination() {
5152
destination.mkdirs();
5253
}
5354
if (!destination.canWrite()) {
54-
throw new JBakeException("Error: Destination folder is not writable: " + destination.getAbsolutePath());
55+
throw new JBakeException(SystemExit.CONFIGURATION_ERROR, "Error: Destination folder is not writable: " + destination.getAbsolutePath());
5556
}
5657
}
5758

@@ -62,9 +63,9 @@ private void checkAssetFolder() {
6263
}
6364
}
6465

65-
private void checkRequiredFolderExists(String property, File path) {
66+
private void checkRequiredFolderExists(String folderName, File path) {
6667
if (!FileUtil.isExistingFolder(path)) {
67-
throw new JBakeException("Error: Required folder cannot be found! Expected to find [" + property + "] at: " + path.getAbsolutePath());
68+
throw new JBakeException(SystemExit.CONFIGURATION_ERROR, "Error: Required folder cannot be found! Expected to find [" + folderName + "] at: " + path.getAbsolutePath());
6869
}
6970
}
7071

jbake-core/src/main/java/org/jbake/launcher/Baker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public void bake(final JBakeConfiguration config) {
4141
msg.append(MessageFormat.format("{0}. {1}\n", errNr, error.getMessage()));
4242
++errNr;
4343
}
44-
throw new JBakeException(msg.toString(), errors.get(0));
44+
throw new JBakeException(SystemExit.ERROR ,msg.toString(), errors.get(0));
4545
}
4646
}
4747
}

jbake-core/src/main/java/org/jbake/launcher/JettyServer.java

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.eclipse.jetty.server.handler.DefaultHandler;
88
import org.eclipse.jetty.server.handler.HandlerList;
99
import org.eclipse.jetty.server.handler.ResourceHandler;
10+
import org.jbake.app.JBakeException;
1011
import org.jbake.app.configuration.JBakeConfiguration;
1112
import org.slf4j.Logger;
1213
import org.slf4j.LoggerFactory;
@@ -34,41 +35,42 @@ public void run(String resourceBase, String port) {
3435
public void run(String resourceBase, JBakeConfiguration configuration) {
3536
run(resourceBase, configuration.getServerContextPath(), configuration.getServerHostname(), configuration.getServerPort());
3637
}
38+
3739
/**
3840
* Run Jetty web server serving out supplied path on supplied port
3941
*
4042
* @param resourceBase Base directory for resources to be served
41-
* @param port Required server port
43+
* @param port Required server port
4244
*/
4345
private void run(String resourceBase, String contextPath, String hostname, int port) {
44-
server = new Server();
45-
ServerConnector connector = new ServerConnector(server);
46-
connector.setHost(hostname);
47-
connector.setPort(port);
48-
server.addConnector(connector);
46+
try {
47+
server = new Server();
48+
ServerConnector connector = new ServerConnector(server);
49+
connector.setHost(hostname);
50+
connector.setPort(port);
51+
server.addConnector(connector);
4952

50-
ResourceHandler resource_handler = new ResourceHandler();
51-
resource_handler.setDirectoriesListed(true);
52-
resource_handler.setWelcomeFiles(new String[]{"index", "index.html"});
53-
resource_handler.setResourceBase(resourceBase);
53+
ResourceHandler resource_handler = new ResourceHandler();
54+
resource_handler.setDirectoriesListed(true);
55+
resource_handler.setWelcomeFiles(new String[]{"index", "index.html"});
56+
resource_handler.setResourceBase(resourceBase);
5457

55-
ContextHandler contextHandler = new ContextHandler();
56-
contextHandler.setContextPath(contextPath);
57-
contextHandler.setHandler(resource_handler);
58+
ContextHandler contextHandler = new ContextHandler();
59+
contextHandler.setContextPath(contextPath);
60+
contextHandler.setHandler(resource_handler);
5861

59-
HandlerList handlers = new HandlerList();
62+
HandlerList handlers = new HandlerList();
6063

61-
handlers.setHandlers(new Handler[]{contextHandler, new DefaultHandler()});
62-
server.setHandler(handlers);
64+
handlers.setHandlers(new Handler[]{contextHandler, new DefaultHandler()});
65+
server.setHandler(handlers);
6366

64-
LOGGER.info("Serving out contents of: [{}] on http://{}:{}{}", resourceBase, hostname, port, contextHandler.getContextPath());
65-
LOGGER.info("(To stop server hit CTRL-C)");
67+
LOGGER.info("Serving out contents of: [{}] on http://{}:{}{}", resourceBase, hostname, port, contextHandler.getContextPath());
68+
LOGGER.info("(To stop server hit CTRL-C)");
6669

67-
try {
6870
server.start();
6971
server.join();
7072
} catch (Exception e) {
71-
LOGGER.error("unable to start server", e);
73+
throw new JBakeException(SystemExit.SERVER_ERROR, "unable to start the server", e);
7274
}
7375
}
7476

jbake-core/src/main/java/org/jbake/launcher/LaunchOptions.java

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,50 @@
11
package org.jbake.launcher;
22

3-
import org.kohsuke.args4j.Argument;
4-
import org.kohsuke.args4j.Option;
3+
import picocli.CommandLine.ArgGroup;
4+
import picocli.CommandLine.Command;
5+
import picocli.CommandLine.Option;
6+
import picocli.CommandLine.Parameters;
57

68
import java.io.File;
79

10+
@Command(
11+
description = "JBake is a Java based, open source, static site/blog generator for developers & designers",
12+
name = "jbake",
13+
usageHelpAutoWidth = true
14+
)
815
public class LaunchOptions {
9-
@Argument(index = 0, usage = "source folder of site content (with templates and assets), if not supplied will default to current directory", metaVar = "<source>")
16+
@Parameters(index = "0", description = "source folder of site content (with templates and assets), if not supplied will default to current directory", arity = "0..1")
1017
private String source;
1118

12-
@Argument(index = 1, usage = "destination folder for output, if not supplied will default to a folder called \"output\" in the current directory", metaVar = "<destination>")
19+
@Parameters(index = "1", description = "destination folder for output, if not supplied will default to a folder called \"output\" in the current directory", arity = "0..1")
1320
private String destination;
1421

15-
@Option(name = "-b", aliases = {"--bake"}, usage = "performs a bake")
22+
@Option(names = {"-b", "--bake"}, description = "performs a bake")
1623
private boolean bake;
1724

18-
@Option(name = "-i", aliases = {"--init"}, usage = "initialises required folder structure with default templates (defaults to current directory if <value> is not supplied)")
19-
private boolean init;
25+
@ArgGroup(exclusive = false, heading = "%n%nJBake initialization%n%n")
26+
private InitOptions initGroup;
2027

21-
@Option(name = "-t", aliases = {"--template"}, usage = "use specified template engine for default templates (uses Freemarker if <value> is not supplied) ", depends = ("-i"))
22-
private String template;
28+
static class InitOptions {
2329

24-
@Option(name = "-s", aliases = {"--server"}, usage = "runs HTTP server to serve out baked site, if no <value> is supplied will default to a folder called \"output\" in the current directory")
30+
@Option(names = {"-i", "--init"}, paramLabel = "<target>", description = "initialises required folder structure with default templates (defaults to current directory if <source> is not supplied)", required = true)
31+
private boolean init;
32+
33+
@Option(names = {"-t", "--template"}, defaultValue = "freemarker", fallbackValue = "freemarker", description = "use specified template engine for default templates (uses Freemarker if <template> is not supplied) ", arity = "0..1")
34+
private String template;
35+
}
36+
37+
@Option(names = {"-s", "--server"}, description = "runs HTTP server to serve out baked site, if no <value> is supplied will default to a folder called \"output\" in the current directory")
2538
private boolean runServer;
2639

27-
@Option(name = "-h", aliases = {"--help"}, usage = "prints this message")
28-
private boolean helpNeeded;
40+
@Option(names = {"-h", "--help"}, description = "prints this message", usageHelp = true)
41+
private boolean helpRequested;
2942

30-
@Option(name = "--reset", usage = "clears the local cache, enforcing rendering from scratch")
43+
@Option(names = {"--reset"}, description = "clears the local cache, enforcing rendering from scratch")
3144
private boolean clearCache;
3245

3346
public String getTemplate() {
34-
if (template != null) {
35-
return template;
36-
} else {
37-
return "freemarker";
38-
}
47+
return initGroup.template;
3948
}
4049

4150
public File getSource() {
@@ -63,15 +72,15 @@ public String getDestinationValue() {
6372
}
6473

6574
public boolean isHelpNeeded() {
66-
return helpNeeded || !(isBake() || isRunServer() || isInit() || source != null || destination != null);
75+
return helpRequested || !(isBake() || isRunServer() || isInit() || source != null || destination != null);
6776
}
6877

6978
public boolean isRunServer() {
7079
return runServer;
7180
}
7281

7382
public boolean isInit() {
74-
return init;
83+
return (initGroup !=null && initGroup.init);
7584
}
7685

7786
public boolean isClearCache() {

0 commit comments

Comments
 (0)