1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix;
19
20 import java.io.File;
21 import java.io.FileDescriptor;
22 import java.io.IOException;
23 import java.io.RandomAccessFile;
24 import java.nio.channels.FileChannel;
25 import java.util.UUID;
26 import java.util.concurrent.atomic.AtomicBoolean;
27
28
29
30
31
32
33 final class RAFChannelProvider extends RandomAccessFile implements FileDescriptorAccess {
34 private final File tempPath;
35 private final FileDescriptor fdObj;
36 private final FileDescriptor rafFdOrig = new FileDescriptor();
37 private final AtomicBoolean closed = new AtomicBoolean(false);
38
39 private RAFChannelProvider(FileDescriptor fdObj) throws IOException {
40 this(fdObj, File.createTempFile("jux", ".sock"));
41 }
42
43 private RAFChannelProvider(FileDescriptor fdObj, File tempPath) throws IOException {
44 super(tempPath, "rw");
45 this.tempPath = tempPath;
46 if (!tempPath.delete() && tempPath.exists()) {
47 if (!tempPath.delete()) {
48
49 }
50 tempPath = new File(tempPath.getParentFile(), "jux-" + UUID.randomUUID().toString()
51 + ".sock");
52 if (tempPath.exists()) {
53 throw new IOException("Could not create a temporary path: " + tempPath);
54 }
55 }
56 tempPath.deleteOnExit();
57
58 NativeUnixSocket.ensureSupported();
59
60 this.fdObj = fdObj;
61
62 FileDescriptor rafFdObj = getFD();
63 NativeUnixSocket.copyFileDescriptor(rafFdObj, rafFdOrig);
64 NativeUnixSocket.copyFileDescriptor(fdObj, rafFdObj);
65 }
66
67 @Override
68 public FileDescriptor getFileDescriptor() {
69 return fdObj;
70 }
71
72 @Override
73 public synchronized void close() throws IOException {
74 if (!closed.getAndSet(true)) {
75 NativeUnixSocket.copyFileDescriptor(rafFdOrig, getFD());
76 if (!tempPath.delete()) {
77
78 }
79 }
80 }
81
82 public static FileChannel getFileChannel(FileDescriptor fd) throws IOException {
83 return getFileChannel0(fd);
84 }
85
86 @SuppressWarnings("resource")
87 private static FileChannel getFileChannel0(FileDescriptor fd) throws IOException {
88 return new RAFChannelProvider(fd).getChannel();
89 }
90 }