Repository: asciidoctor/asciidoctorj
Issue: Asciidoctorj gives error if input file is an absolute path

Hi,

I have error if I pass the input file as an absolute path, but using relative path everything is ok.

Asciidoctorj version (installed via GVM):

```
enrico@lap:~/union/feasibility-docs/developers-manual$ asciidoctorj --version
Asciidoctor 1.5.2 [http://asciidoctor.org]
```

The failing command:

```
enrico@lap:~/union/feasibility-docs/developers-manual$ asciidoctorj --backend html5 \\
--destination-dir /home/enrico/union/feasibility-docs/developers-manual/build \\
--out-file index.html --doctype book --attribute project-version=0.1 \\
/home/enrico/union/feasibility-docs/developers-manual/src/asciidoc/index.adoc
asciidoctor: FAILED: input file(s) '[/home/enrico/union/feasibility-docs/developers-manual/src/asciidoc/index.adoc]' missing or cannot be read
Exception in thread "main" java.lang.IllegalArgumentException: asciidoctor: FAILED: input file(s) '[/home/enrico/union/feasibility-docs/developers-manual/src/asciidoc/index.adoc]' missing or cannot be read
at org.asciidoctor.cli.AsciidoctorInvoker.invoke(AsciidoctorInvoker.java:51)
at org.asciidoctor.cli.AsciidoctorInvoker.main(AsciidoctorInvoker.java:184)
```

The input file exists:

```
enrico@lap:~/union/feasibility-docs/developers-manual$ ll /home/enrico/union/feasibility-docs/developers-manual/src/asciidoc/index.adoc
-rw-rw-r-- 1 enrico enrico 288 gen 27 16:39 /home/enrico/union/feasibility-docs/developers-manual/src/asciidoc/index.adoc
```

The successful command (change only the input file path, from absolute to relative):

```
enrico@lap:~/union/feasibility-docs/developers-manual$ asciidoctorj --backend html5 \\
--destination-dir /home/enrico/union/feasibility-docs/developers-manual/build \\
--out-file index.html --doctype book --attribute project-version=0.1 \\
src/asciidoc/index.adoc
```

Is this expected?

Anyway, thanks a lot for this awesome tool!

Enrico


Changed files:
asciidoctorj-core/src/test/java/org/asciidoctor/WhenGlobExpressionIsUsedForScanning.java
asciidoctorj-core/src/main/java/org/asciidoctor/GlobDirectoryWalker.java
asciidoctorj-core/src/test/java/org/asciidoctor/cli/WhenAsciidoctorIsCalledUsingCli.java
asciidoctorj-core/src/main/java/org/asciidoctor/cli/AsciidoctorInvoker.java

diff --git a/asciidoctorj-core/src/main/java/org/asciidoctor/GlobDirectoryWalker.java b/asciidoctorj-core/src/main/java/org/asciidoctor/GlobDirectoryWalker.java
index 907b3ff7..a87fd80a 100644
--- a/asciidoctorj-core/src/main/java/org/asciidoctor/GlobDirectoryWalker.java
+++ b/asciidoctorj-core/src/main/java/org/asciidoctor/GlobDirectoryWalker.java
@@ -24,11 +24,63 @@ public class GlobDirectoryWalker implements DirectoryWalker {
     private final List<File> matches = new ArrayList<File>();
     private final String globExpression;
 
-    public GlobDirectoryWalker(String rootDir, String globExpression) {
-        rootDirectory = new File(rootDir);
-        checkInput(rootDirectory);
-        this.canonicalRootDir = getCanonicalPath(rootDirectory);
-        this.globExpression = globExpression;
+    public GlobDirectoryWalker(String globExpression) {
+
+        if (isAbsoluteGlobExpression(globExpression)) {
+
+            // If the given path is an absolute path we want to split it into an absolute part containing
+            // directories without wildcards and a glob part with wildcards and file names
+            int indexOfUnglobbedPart = findIndexOfUnglobbedPart(globExpression);
+            this.rootDirectory = new File(globExpression.substring(0, indexOfUnglobbedPart));
+            this.globExpression = globExpression.substring(indexOfUnglobbedPart + 1);
+            checkInput(rootDirectory);
+            this.canonicalRootDir = getCanonicalPath(rootDirectory);
+
+        } else {
+            // It's a relative expression, current working dir is sufficient as root directory
+            rootDirectory = new File(".");
+            checkInput(rootDirectory);
+            this.canonicalRootDir = getCanonicalPath(rootDirectory);
+            this.globExpression = globExpression;
+
+        }
+    }
+
+    // An absolute path will consist of an absolute, unglobbed part and a globbed part.
+    // The globbed part starts at the first path element that contains a '*' or it is
+    // the part following the last separator
+    private int findIndexOfUnglobbedPart(String globExpression) {
+        int result = 0;
+        for (int i = 0; i < globExpression.length(); i++) {
+            switch (globExpression.charAt(i)) {
+                case '/':
+                case '\\\\':
+                    result = i;
+                    break;
+                case '*':
+                    return result;
+                default:
+            }
+        }
+        // There is apparently no wildcard in the path, let the directory part be the path
+        // and the glob part only the filename
+        return result;
+    }
+
+    // Determines if the given glob expression is an absolute path
+    // That is the expression starts with a separator or with [A-Za-z]:[/\\] on Windows
+    private boolean isAbsoluteGlobExpression(String globExpression) {
+        if (globExpression.startsWith(File.separator)) {
+            return true;
+        }
+        if (isWindows()) {
+            return globExpression.matches("^[A-Za-z]:[\\\\\\\\/].*$");
+        }
+        return false;
+    }
+
+    private boolean isWindows() {
+        return System.getProperty("os.name").toLowerCase().contains("win");
     }
 
     @Override
diff --git a/asciidoctorj-core/src/main/java/org/asciidoctor/cli/AsciidoctorInvoker.java b/asciidoctorj-core/src/main/java/org/asciidoctor/cli/AsciidoctorInvoker.java
index 0da5fd57..c068a3cd 100644
--- a/asciidoctorj-core/src/main/java/org/asciidoctor/cli/AsciidoctorInvoker.java
+++ b/asciidoctorj-core/src/main/java/org/asciidoctor/cli/AsciidoctorInvoker.java
@@ -171,8 +171,7 @@ public class AsciidoctorInvoker {
         List<File> filesToBeRendered = new ArrayList<File>();
 
         for (String globExpression : parameters) {
-            DirectoryWalker globDirectoryWalker = new GlobDirectoryWalker(".",
-                    globExpression);
+            DirectoryWalker globDirectoryWalker = new GlobDirectoryWalker(globExpression);
             filesToBeRendered.addAll(globDirectoryWalker.scan());
         }
 
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenGlobExpressionIsUsedForScanning.java b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenGlobExpressionIsUsedForScanning.java
index 01aeba5d..140b5563 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenGlobExpressionIsUsedForScanning.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenGlobExpressionIsUsedForScanning.java
@@ -21,7 +21,7 @@ public class WhenGlobExpressionIsUsedForScanning {
     public void all_files_with_given_extension_of_current_directory_should_be_returned() {
         
         File pathToWalk = classpath.getResource("src");
-        DirectoryWalker globDirectoryWalker = new GlobDirectoryWalker(pathToWalk.getPath(), "documents/*.adoc");
+        DirectoryWalker globDirectoryWalker = new GlobDirectoryWalker(pathToWalk.getPath() + File.separator + "documents/*.adoc");
         List<File> asciidocFiles = globDirectoryWalker.scan();
         
         assertThat(
@@ -35,7 +35,7 @@ public class WhenGlobExpressionIsUsedForScanning {
     public void all_files_with_given_extension_should_be_returned_recursively() {
         
         File pathToWalk = classpath.getResource("src");
-        DirectoryWalker globDirectoryWalker = new GlobDirectoryWalker(pathToWalk.getPath(), "**/*.adoc");
+        DirectoryWalker globDirectoryWalker = new GlobDirectoryWalker(pathToWalk.getPath() + File.separator + "**/*.adoc");
         List<File> asciidocFiles = globDirectoryWalker.scan();
         
         assertThat(
@@ -49,7 +49,7 @@ public class WhenGlobExpressionIsUsedForScanning {
     public void no_should_be_returned_if_glob_expression_does_not_match() {
         
         File pathToWalk = classpath.getResource("src");
-        DirectoryWalker globDirectoryWalker = new GlobDirectoryWalker(pathToWalk.getPath(), "**/*.a");
+        DirectoryWalker globDirectoryWalker = new GlobDirectoryWalker(pathToWalk.getPath() + File.separator + "**/*.a");
         List<File> asciidocFiles = globDirectoryWalker.scan();
         
         assertThat(asciidocFiles, is(empty()));
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/cli/WhenAsciidoctorIsCalledUsingCli.java b/asciidoctorj-core/src/test/java/org/asciidoctor/cli/WhenAsciidoctorIsCalledUsingCli.java
index 97578201..d1c13c80 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/cli/WhenAsciidoctorIsCalledUsingCli.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/cli/WhenAsciidoctorIsCalledUsingCli.java
@@ -231,7 +231,19 @@ public class WhenAsciidoctorIsCalledUsingCli {
 	    
 	}
 
-	private ByteArrayOutputStream redirectStdout() {
+    @Test
+    public void with_absolute_path_file_should_be_rendered() {
+
+        File inputFile = classpath.getResource("rendersample.asciidoc");
+        String inputPath = inputFile.getAbsolutePath();
+        new AsciidoctorInvoker().invoke(inputPath);
+        File expectedFile = new File(inputPath.replaceFirst("\\\\.asciidoc$", ".html"));
+
+        assertThat(expectedFile.exists(), is(true));
+        expectedFile.delete();
+    }
+
+    private ByteArrayOutputStream redirectStdout() {
 		ByteArrayOutputStream output = new ByteArrayOutputStream();
 		System.setOut(new PrintStream(output));
 		return output;