NioPathDeserializer improvement (#2120)

diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/NioPathDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/ext/NioPathDeserializer.java
index 48a39eb..20e9d5c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ext/NioPathDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/NioPathDeserializer.java
@@ -1,16 +1,22 @@
 package com.fasterxml.jackson.databind.ext;
 
+import java.io.File;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.nio.file.FileSystemNotFoundException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.ServiceLoader;
 
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
 import com.fasterxml.jackson.databind.DeserializationContext;
 import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
 
+import static java.lang.Character.isLetter;
+
 /**
  * @since 2.8
  */
@@ -18,6 +24,19 @@
 {
     private static final long serialVersionUID = 1;
 
+    private static final boolean areWindowsFilePathsSupported;
+    static {
+        boolean isWindowsRootFound = false;
+        for (File file : File.listRoots()) {
+            String path = file.getPath();
+            if (path.length() >= 2 && isLetter(path.charAt(0)) && path.charAt(1) == ':') {
+                isWindowsRootFound = true;
+                break;
+            }
+        }
+        areWindowsFilePathsSupported = isWindowsRootFound;
+    }
+
     public NioPathDeserializer() { super(Path.class); }
 
     @Override
@@ -25,17 +44,45 @@
         if (!p.hasToken(JsonToken.VALUE_STRING)) {
             return (Path) ctxt.handleUnexpectedToken(Path.class, p);
         }
+
         final String value = p.getText();
+
         // If someone gives us an input with no : at all, treat as local path, instead of failing
         // with invalid URI.
         if (value.indexOf(':') < 0) {
             return Paths.get(value);
         }
+
+        if (areWindowsFilePathsSupported) {
+            if (value.length() >= 2 && isLetter(value.charAt(0)) && value.charAt(1) == ':') {
+                return Paths.get(value);
+            }
+        }
+
+        final URI uri;
         try {
-            URI uri = new URI(value);
-            return Paths.get(uri);
+            uri = new URI(value);
         } catch (URISyntaxException e) {
             return (Path) ctxt.handleInstantiationProblem(handledType(), value, e);
         }
+        try {
+            return Paths.get(uri);
+        } catch (FileSystemNotFoundException cause) {
+            try {
+                final String scheme = uri.getScheme();
+                // We want to use the current thread's context class loader, not system class loader that is used in Paths.get():
+                for (FileSystemProvider provider : ServiceLoader.load(FileSystemProvider.class)) {
+                    if (provider.getScheme().equalsIgnoreCase(scheme)) {
+                        return provider.getPath(uri);
+                    }
+                }
+                return (Path) ctxt.handleInstantiationProblem(handledType(), value, cause);
+            } catch (Throwable e) {
+                e.addSuppressed(cause);
+                return (Path) ctxt.handleInstantiationProblem(handledType(), value, e);
+            }
+        } catch (Throwable e) {
+            return (Path) ctxt.handleInstantiationProblem(handledType(), value, e);
+        }
     }
 }