Skip to content

Commit c570b0a

Browse files
remalcowtowncoder
authored andcommitted
NioPathDeserializer improvement (#2120)
1 parent 5256bfc commit c570b0a

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,88 @@
11
package com.fasterxml.jackson.databind.ext;
22

3+
import java.io.File;
34
import java.io.IOException;
45
import java.net.URI;
56
import java.net.URISyntaxException;
7+
import java.nio.file.FileSystemNotFoundException;
68
import java.nio.file.Path;
79
import java.nio.file.Paths;
10+
import java.nio.file.spi.FileSystemProvider;
11+
import java.util.ServiceLoader;
812

913
import com.fasterxml.jackson.core.JsonParser;
1014
import com.fasterxml.jackson.core.JsonToken;
1115
import com.fasterxml.jackson.databind.DeserializationContext;
1216
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
1317

18+
import static java.lang.Character.isLetter;
19+
1420
/**
1521
* @since 2.8
1622
*/
1723
public class NioPathDeserializer extends StdScalarDeserializer<Path>
1824
{
1925
private static final long serialVersionUID = 1;
2026

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+
2140
public NioPathDeserializer() { super(Path.class); }
2241

2342
@Override
2443
public Path deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
2544
if (!p.hasToken(JsonToken.VALUE_STRING)) {
2645
return (Path) ctxt.handleUnexpectedToken(Path.class, p);
2746
}
47+
2848
final String value = p.getText();
49+
2950
// If someone gives us an input with no : at all, treat as local path, instead of failing
3051
// with invalid URI.
3152
if (value.indexOf(':') < 0) {
3253
return Paths.get(value);
3354
}
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;
3463
try {
35-
URI uri = new URI(value);
36-
return Paths.get(uri);
64+
uri = new URI(value);
3765
} catch (URISyntaxException e) {
3866
return (Path) ctxt.handleInstantiationProblem(handledType(), value, e);
3967
}
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+
}
4087
}
4188
}

0 commit comments

Comments
 (0)