• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.ext;
2 
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.URI;
6 import java.net.URISyntaxException;
7 import java.nio.file.FileSystemNotFoundException;
8 import java.nio.file.Path;
9 import java.nio.file.Paths;
10 import java.nio.file.spi.FileSystemProvider;
11 import java.util.ServiceLoader;
12 
13 import com.fasterxml.jackson.core.JsonParser;
14 import com.fasterxml.jackson.core.JsonToken;
15 import com.fasterxml.jackson.databind.DeserializationContext;
16 import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
17 
18 import static java.lang.Character.isLetter;
19 
20 /**
21  * @since 2.8
22  */
23 public class NioPathDeserializer extends StdScalarDeserializer<Path>
24 {
25     private static final long serialVersionUID = 1;
26 
27     private static final boolean areWindowsFilePathsSupported;
28     static {
29         boolean isWindowsRootFound = false;
30         for (File file : File.listRoots()) {
31             String path = file.getPath();
32             if (path.length() >= 2 && isLetter(path.charAt(0)) && path.charAt(1) == ':') {
33                 isWindowsRootFound = true;
34                 break;
35             }
36         }
37         areWindowsFilePathsSupported = isWindowsRootFound;
38     }
39 
NioPathDeserializer()40     public NioPathDeserializer() { super(Path.class); }
41 
42     @Override
deserialize(JsonParser p, DeserializationContext ctxt)43     public Path deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
44         if (!p.hasToken(JsonToken.VALUE_STRING)) {
45             return (Path) ctxt.handleUnexpectedToken(Path.class, p);
46         }
47 
48         final String value = p.getText();
49 
50         // If someone gives us an input with no : at all, treat as local path, instead of failing
51         // with invalid URI.
52         if (value.indexOf(':') < 0) {
53             return Paths.get(value);
54         }
55 
56         if (areWindowsFilePathsSupported) {
57             if (value.length() >= 2 && isLetter(value.charAt(0)) && value.charAt(1) == ':') {
58                 return Paths.get(value);
59             }
60         }
61 
62         final URI uri;
63         try {
64             uri = new URI(value);
65         } catch (URISyntaxException e) {
66             return (Path) ctxt.handleInstantiationProblem(handledType(), value, e);
67         }
68         try {
69             return Paths.get(uri);
70         } catch (FileSystemNotFoundException cause) {
71             try {
72                 final String scheme = uri.getScheme();
73                 // We want to use the current thread's context class loader, not system class loader that is used in Paths.get():
74                 for (FileSystemProvider provider : ServiceLoader.load(FileSystemProvider.class)) {
75                     if (provider.getScheme().equalsIgnoreCase(scheme)) {
76                         return provider.getPath(uri);
77                     }
78                 }
79                 return (Path) ctxt.handleInstantiationProblem(handledType(), value, cause);
80             } catch (Throwable e) {
81                 e.addSuppressed(cause);
82                 return (Path) ctxt.handleInstantiationProblem(handledType(), value, e);
83             }
84         } catch (Throwable e) {
85             return (Path) ctxt.handleInstantiationProblem(handledType(), value, e);
86         }
87     }
88 }
89