Skip to content

Commit 4e05cab

Browse files
authored
Merge pull request #41
* Try and make ourselves a lot less vulnerable to Thread interruption, … * Try and detect if we've lost our zipfilesystem due to an unexpected c…
1 parent b466618 commit 4e05cab

3 files changed

Lines changed: 50 additions & 11 deletions

File tree

src/main/java/cpw/mods/cl/UnionURLStreamHandler.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package cpw.mods.cl;
22

3+
import cpw.mods.niofs.union.UnionPath;
4+
35
import java.io.IOException;
46
import java.io.InputStream;
57
import java.io.UncheckedIOException;
@@ -19,11 +21,13 @@ public String protocol() {
1921
public Function<URL, InputStream> inputStreamFunction() {
2022
return u-> {
2123
try {
22-
return Files.newInputStream(Paths.get(u.toURI()));
24+
if (Paths.get(u.toURI()) instanceof UnionPath upath) {
25+
return upath.buildInputStream();
26+
} else {
27+
throw new IllegalArgumentException("Invalid Path "+u.toURI()+" at UnionURLStreamHandler");
28+
}
2329
} catch (URISyntaxException e) {
2430
throw new RuntimeException(e);
25-
} catch (IOException e) {
26-
throw new UncheckedIOException(e);
2731
}
2832

2933

src/main/java/cpw/mods/niofs/union/UnionFileSystem.java

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package cpw.mods.niofs.union;
22

3-
import java.io.FileNotFoundException;
4-
import java.io.IOException;
3+
import java.io.*;
54
import java.lang.invoke.MethodHandle;
65
import java.lang.invoke.MethodHandles;
76
import java.lang.invoke.MethodType;
7+
import java.lang.reflect.Method;
8+
import java.nio.channels.ClosedByInterruptException;
9+
import java.nio.channels.FileChannel;
10+
import java.nio.channels.InterruptibleChannel;
811
import java.nio.channels.SeekableByteChannel;
912
import java.nio.file.AccessMode;
1013
import java.nio.file.DirectoryStream;
@@ -37,8 +40,12 @@
3740

3841
public class UnionFileSystem extends FileSystem {
3942
private static final MethodHandle ZIPFS_EXISTS;
43+
private static final MethodHandle ZIPFS_CH;
44+
private static final MethodHandle FCI_UNINTERUPTIBLE;
4045
static final String SEP_STRING = "/";
4146

47+
48+
4249
static {
4350
try {
4451
var hackfield = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
@@ -47,10 +54,27 @@ public class UnionFileSystem extends FileSystem {
4754

4855
var clz = Class.forName("jdk.nio.zipfs.ZipPath");
4956
ZIPFS_EXISTS = hack.findSpecial(clz, "exists", MethodType.methodType(boolean.class), clz);
57+
58+
clz = Class.forName("jdk.nio.zipfs.ZipFileSystem");
59+
ZIPFS_CH = hack.findGetter(clz, "ch", SeekableByteChannel.class);
60+
61+
clz = Class.forName("sun.nio.ch.FileChannelImpl");
62+
FCI_UNINTERUPTIBLE = hack.findSpecial(clz, "setUninterruptible", MethodType.methodType(void.class), clz);
5063
} catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException e) {
5164
throw new RuntimeException(e);
5265
}
5366
}
67+
68+
public InputStream buildInputStream(final UnionPath path) {
69+
try {
70+
var bytes = Files.readAllBytes(path);
71+
return new ByteArrayInputStream(bytes);
72+
} catch (IOException ioe)
73+
{
74+
throw new UncheckedIOException(ioe);
75+
}
76+
}
77+
5478
private static class NoSuchFileException extends java.nio.file.NoSuchFileException {
5579
public NoSuchFileException(final String file) {
5680
super(file);
@@ -91,7 +115,7 @@ String getKey() {
91115
return this.key;
92116
}
93117

94-
private record EmbeddedFileSystemMetadata(Path path, FileSystem fs) {}
118+
private record EmbeddedFileSystemMetadata(Path path, FileSystem fs, SeekableByteChannel fsCh) {}
95119

96120
public UnionFileSystem(final UnionFileSystemProvider provider, final BiPredicate<String, String> pathFilter, final String key, final Path... basepaths) {
97121
this.pathFilter = pathFilter;
@@ -109,9 +133,14 @@ public UnionFileSystem(final UnionFileSystemProvider provider, final BiPredicate
109133

110134
private static Optional<EmbeddedFileSystemMetadata> openFileSystem(final Path path) {
111135
try {
112-
return Optional.of(new EmbeddedFileSystemMetadata(path, FileSystems.newFileSystem(path)));
136+
var zfs = FileSystems.newFileSystem(path);
137+
FileChannel fci = (FileChannel) ZIPFS_CH.invoke(zfs);
138+
FCI_UNINTERUPTIBLE.invoke(fci);
139+
return Optional.of(new EmbeddedFileSystemMetadata(path, zfs, fci));
113140
} catch (IOException e) {
114141
throw new UncheckedIOException(e);
142+
} catch (Throwable t) {
143+
throw new IllegalStateException(t);
115144
}
116145
}
117146

@@ -197,7 +226,7 @@ private Optional<BasicFileAttributes> getFileAttributes(final Path path) {
197226
try {
198227
if (path.getFileSystem() == FileSystems.getDefault() && !path.toFile().exists()) {
199228
return Optional.empty();
200-
} else if (path.getFileSystem().provider().getScheme().equals("jar") && !zipFsExists(path)) {
229+
} else if (path.getFileSystem().provider().getScheme().equals("jar") && !zipFsExists(this, path)) {
201230
return Optional.empty();
202231
} else {
203232
return Optional.of(path.getFileSystem().provider().readAttributes(path, BasicFileAttributes.class));
@@ -215,8 +244,9 @@ private Optional<Path> findFirstPathAt(final UnionPath path) {
215244
.findFirst();
216245
}
217246

218-
private static boolean zipFsExists(Path path) {
247+
private static boolean zipFsExists(UnionFileSystem ufs, Path path) {
219248
try {
249+
if (Optional.ofNullable(ufs.embeddedFileSystems.get(path.getFileSystem())).filter(efs->!efs.fsCh.isOpen()).isPresent()) throw new IllegalStateException("The zip file has closed!");
220250
return (boolean) ZIPFS_EXISTS.invoke(path);
221251
} catch (Throwable t) {
222252
throw new IllegalStateException(t);
@@ -231,7 +261,7 @@ private Optional<Path> findFirstFiltered(final UnionPath path) {
231261
return Optional.of(realPath);
232262
}
233263
} else if (realPath.getFileSystem().provider().getScheme().equals("jar")) {
234-
if (zipFsExists(realPath)) {
264+
if (zipFsExists(this, realPath)) {
235265
return Optional.of(realPath);
236266
}
237267
} else if (Files.exists(realPath)) {
@@ -327,7 +357,7 @@ public DirectoryStream<Path> newDirStream(final UnionPath path, final DirectoryS
327357
continue;
328358
} else if (dir.getFileSystem() == FileSystems.getDefault() && !dir.toFile().exists()) {
329359
continue;
330-
} else if (dir.getFileSystem().provider().getScheme() == "jar" && !zipFsExists(dir)) {
360+
} else if (dir.getFileSystem().provider().getScheme() == "jar" && !zipFsExists(this, dir)) {
331361
continue;
332362
} else if (Files.notExists(dir)) {
333363
continue;

src/main/java/cpw/mods/niofs/union/UnionPath.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cpw.mods.niofs.union;
22

33
import java.io.IOException;
4+
import java.io.InputStream;
45
import java.net.URI;
56
import java.net.URISyntaxException;
67
import java.nio.file.LinkOption;
@@ -325,4 +326,8 @@ public int hashCode() {
325326
public String toString() {
326327
return (this.absolute ? UnionFileSystem.SEP_STRING : "") + String.join(UnionFileSystem.SEP_STRING, this.pathParts);
327328
}
329+
330+
public InputStream buildInputStream() {
331+
return fileSystem.buildInputStream(this);
332+
}
328333
}

0 commit comments

Comments
 (0)