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.IOException;
21 import java.nio.channels.AsynchronousCloseException;
22 import java.nio.channels.ClosedByInterruptException;
23 import java.nio.channels.ClosedChannelException;
24 import java.nio.channels.NotYetBoundException;
25 import java.nio.channels.NotYetConnectedException;
26 import java.nio.channels.spi.AbstractInterruptibleChannel;
27 import java.util.Objects;
28
29
30
31
32
33
34 final class InterruptibleChannelUtil {
35
36
37
38 @FunctionalInterface
39 interface EndMethod {
40 void end(boolean completed) throws AsynchronousCloseException;
41 }
42
43
44
45
46
47
48
49
50
51
52
53
54
55 static void endInterruptable(AFSomeSocketChannel channel, EndMethod end, boolean complete,
56 Exception exception) throws AsynchronousCloseException {
57 if (!complete) {
58 if (exception instanceof ClosedChannelException) {
59
60 complete = true;
61 }
62 }
63 try {
64 end.end(complete);
65 } catch (AsynchronousCloseException e) {
66 throw closeAndThrow(channel, e);
67 }
68 }
69
70 private static <T extends Exception> T closeAndThrow(AFSomeSocketChannel channel, T exc) {
71 Objects.requireNonNull(exc);
72 if (channel.isOpen()) {
73 try {
74 channel.close();
75 } catch (IOException e2) {
76 exc.addSuppressed(e2);
77 }
78 }
79 return exc;
80 }
81
82 static IOException ioExceptionOrThrowRuntimeException(Exception exception) {
83 if (exception instanceof IOException) {
84 return (IOException) exception;
85 } else if (exception instanceof RuntimeException) {
86 throw (RuntimeException) exception;
87 } else {
88 throw new IllegalStateException(exception);
89 }
90 }
91
92
93
94
95
96
97
98
99
100
101 @SuppressWarnings("PMD.CognitiveComplexity")
102 static Exception handleException(AFSomeSocketChannel channel, IOException e) {
103 if (e instanceof NotConnectedSocketException) {
104 return (NotYetConnectedException) new NotYetConnectedException().initCause(e);
105 } else if (e instanceof NotBoundSocketException) {
106 return (NotYetBoundException) new NotYetBoundException().initCause(e);
107 }
108
109 if (e instanceof InvalidArgumentSocketException) {
110 if (channel instanceof AFServerSocketChannel<?>) {
111 AFServerSocketChannel<?> sc = (AFServerSocketChannel<?>) channel;
112 if (!sc.socket().isBound()) {
113 return (NotYetBoundException) new NotYetBoundException().initCause(e);
114 }
115 } else if (channel instanceof AFSocketChannel<?>) {
116 if (!((AFSocketChannel<?>) channel).socket().isConnected()) {
117 return (NotYetConnectedException) new NotYetConnectedException().initCause(e);
118 }
119 }
120 }
121
122 if (e instanceof SocketClosedException || e instanceof ClosedChannelException
123 || e instanceof BrokenPipeSocketException) {
124 Thread t = Thread.currentThread();
125
126 if (e instanceof SocketClosedByInterruptException
127 || e instanceof ClosedByInterruptException) {
128 if (!t.isInterrupted()) {
129 t.interrupt();
130 }
131 }
132
133 if (!(e instanceof ClosedChannelException)) {
134
135 if (t.isInterrupted()) {
136 e = (ClosedByInterruptException) new ClosedByInterruptException().initCause(e);
137 } else if (e instanceof BrokenPipeSocketException) {
138 e = (AsynchronousCloseException) new AsynchronousCloseException().initCause(e);
139 } else {
140 e = (ClosedChannelException) new ClosedChannelException().initCause(e);
141 }
142 }
143
144 return closeAndThrow(channel, e);
145 } else {
146 return e;
147 }
148 }
149 }