diff --git a/README.md b/README.md index 6cef48003..0681f00d1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # JBake -[![Build Status](https://travis-ci.org/jonbullock/JBake.png?branch=master)](https://travis-ci.org/jonbullock/JBake) +![Build Status](https://travis-ci.org/mismatch/JBake.png?branch=master) by **[Jonathan Bullock](http://jonathanbullock.com/)** diff --git a/pom.xml b/pom.xml index e33f77484..be941e2ee 100644 --- a/pom.xml +++ b/pom.xml @@ -112,6 +112,11 @@ commons-configuration 1.9 + + args4j + args4j + 2.0.23 + org.freemarker freemarker diff --git a/src/main/java/org/jbake/app/FileUtil.java b/src/main/java/org/jbake/app/FileUtil.java index 2067c1ee6..c15514a65 100644 --- a/src/main/java/org/jbake/app/FileUtil.java +++ b/src/main/java/org/jbake/app/FileUtil.java @@ -27,4 +27,8 @@ public boolean accept(File pathname) { } }; } + + public static boolean isExistingFolder(File f) { + return null != f && f.exists() && f.isDirectory(); + } } diff --git a/src/main/java/org/jbake/app/Oven.java b/src/main/java/org/jbake/app/Oven.java index 4b0b66003..adaadc32a 100644 --- a/src/main/java/org/jbake/app/Oven.java +++ b/src/main/java/org/jbake/app/Oven.java @@ -36,18 +36,49 @@ public class Oven { * * @param source The source folder * @param destination The destination folder - * @throws ConfigurationException + * @throws Exception */ - public Oven(File source, File destination) throws ConfigurationException { + public Oven(File source, File destination) throws Exception { this.source = source; this.destination = destination; + + ensureSource(); + + loadConfig(); + + ensureDestination(); + } + + private void loadConfig() throws ConfigurationException { this.config = new CompositeConfiguration(); - File customConfig = new File(source.getPath()+File.separator+"custom.properties"); + File customConfig = new File(source, "custom.properties"); if (customConfig.exists()) { config.addConfiguration(new PropertiesConfiguration(customConfig)); } config.addConfiguration(new PropertiesConfiguration("default.properties")); - } + } + + private void ensureSource() throws Exception { + if (!FileUtil.isExistingFolder(source)) { + throw new Exception("Source folder MUST exist!"); + } + if (!source.canRead()) { + throw new Exception("Source folder is not readable! Please, check"); + } + } + + + private void ensureDestination() throws Exception { + if (null == destination) { + destination = new File(config.getString("destination.folder")); + } + if (!destination.exists()) { + destination.mkdirs(); + } + if (!destination.canWrite()) { + throw new Exception("Destination folder is not writable! Please, check"); + } + } /** * Checks source path contains required sub-folders (i.e. templates) and setups up variables for them. @@ -55,20 +86,26 @@ public Oven(File source, File destination) throws ConfigurationException { * @throws Exception If template or contents folder don't exist */ public void setupPaths() throws Exception { - templatesPath = new File(source.getPath() + File.separator + config.getString("template.folder")); - if (!templatesPath.exists()) { - throw new Exception("Error: Required template folder cannot be found!"); - } - contentsPath = new File(source.getPath() + File.separator + config.getString("content.folder")); - if (!contentsPath.exists()) { - throw new Exception("Error: Required content folder cannot be found!"); - } - assetsPath = new File(source.getPath() + File.separator + config.getString("asset.folder")); + templatesPath = setupRequiredFolderFromConfig("template.folder"); + contentsPath = setupRequiredFolderFromConfig("content.folder"); + assetsPath = setupPathFromConfig("asset.folder"); if (!assetsPath.exists()) { System.out.println("Warning: No asset folder was found!"); } } + private File setupPathFromConfig(String key) { + return new File(source, config.getString(key)); + } + + private File setupRequiredFolderFromConfig(String key) throws Exception { + File path = setupPathFromConfig(key); + if (!FileUtil.isExistingFolder(path)) { + throw new Exception("Error: Required folder cannot be found! Config key is " + key); + } + return path; + } + /** * All the good stuff happens in here... * diff --git a/src/main/java/org/jbake/launcher/LaunchOptions.java b/src/main/java/org/jbake/launcher/LaunchOptions.java new file mode 100644 index 000000000..3e1040d8c --- /dev/null +++ b/src/main/java/org/jbake/launcher/LaunchOptions.java @@ -0,0 +1,32 @@ +package org.jbake.launcher; + +import java.io.File; + +import org.kohsuke.args4j.Argument; +import org.kohsuke.args4j.Option; + +class LaunchOptions { + @Argument(index = 0, usage = "source of your blog posts (with templates and assets)", metaVar = "source_folder") + private File source = new File("."); + + @Argument(index = 1, usage = "destination folder for baked artifacts", metaVar = "destination_folder") + private File destination = null; + + @Option(name = "-h", aliases = {"--help"}, usage="prints this message") + private boolean isHelpNeeded; + + + LaunchOptions() {} + + File getSource() { + return source; + } + + File getDestination() { + return destination; + } + + boolean isHelpNeeded() { + return isHelpNeeded; + } +} diff --git a/src/main/java/org/jbake/launcher/Main.java b/src/main/java/org/jbake/launcher/Main.java index 91c9a2dff..f159d4abc 100644 --- a/src/main/java/org/jbake/launcher/Main.java +++ b/src/main/java/org/jbake/launcher/Main.java @@ -1,6 +1,10 @@ package org.jbake.launcher; import java.io.File; +import java.io.StringWriter; + +import org.kohsuke.args4j.CmdLineException; +import org.kohsuke.args4j.CmdLineParser; import org.jbake.app.Oven; @@ -11,9 +15,9 @@ * */ public class Main { - public static final String VERSION = "v2.0"; - private static final String USAGE = "Usage: java -jar jbake.jar "; + + private final String USAGE_PREFIX = "Usage: java -jar jbake.jar"; /** * Runs the app with the given arguments. @@ -21,28 +25,45 @@ public class Main { * @param String[] args */ public static void main(String[] args) { - if (args.length == 0) { - System.out.println(USAGE); - } else { - if (args.length != 2) { - System.out.println(USAGE); - } else { - File source = new File(args[0]); - File destination = new File(args[1]); - if (!source.exists() || !destination.exists()) { - System.out.println(USAGE); - } else { - try { - Oven oven = new Oven(source, destination); - oven.setupPaths(); - oven.bake(); - } catch (Exception e) { - e.printStackTrace(); - } - - } + Main m = new Main(); + m.run(m.parseArguments(args)); + } + + private void run(LaunchOptions options) { + try { + Oven oven = new Oven(options.getSource(), options.getDestination()); + oven.setupPaths(); + oven.bake(); + } catch (Exception e) { + System.err.println(e.getMessage()); + e.printStackTrace(); + } + } + + private LaunchOptions parseArguments(String[] args) { + LaunchOptions res = new LaunchOptions(); + CmdLineParser parser = new CmdLineParser(res); + + try { + parser.parseArgument(args); + + if (res.isHelpNeeded()) { + printUsage(parser); } + } catch (CmdLineException e) { + printUsage(parser); } + + return res; + } + + private void printUsage(CmdLineParser parser) { + StringWriter sw = new StringWriter(); + sw.append(USAGE_PREFIX); + parser.printSingleLineUsage(sw, null); + System.out.println(sw.toString()); + parser.printUsage(System.out); + System.exit(0); } } diff --git a/src/main/resources/default.properties b/src/main/resources/default.properties index b56913dbd..b40497348 100644 --- a/src/main/resources/default.properties +++ b/src/main/resources/default.properties @@ -1,3 +1,5 @@ +# path to destination folder by default +destination.folder=baked # folder that contains all template files template.folder=templates # filename of index template file @@ -31,4 +33,4 @@ tag.path=tags # file extension for output content files output.extension=.html # draft content suffix -draft.suffix=-draft \ No newline at end of file +draft.suffix=-draft