44import com .sun .jna .win32 .StdCallLibrary ;
55import com .sun .jna .win32 .W32APIOptions ;
66
7- import java .io .FileNotFoundException ;
87import java .io .IOException ;
98import java .io .InputStream ;
109import java .io .OutputStream ;
11- import java .io .RandomAccessFile ;
1210import java .net .Socket ;
1311import java .net .SocketAddress ;
12+ import java .nio .ByteBuffer ;
13+ import java .nio .channels .AsynchronousByteChannel ;
14+ import java .nio .channels .AsynchronousCloseException ;
15+ import java .nio .channels .AsynchronousFileChannel ;
16+ import java .nio .channels .Channels ;
17+ import java .nio .channels .CompletionHandler ;
18+ import java .nio .file .NoSuchFileException ;
19+ import java .nio .file .Paths ;
20+ import java .nio .file .StandardOpenOption ;
21+ import java .util .concurrent .CompletableFuture ;
22+ import java .util .concurrent .Future ;
1423
1524class NamedPipeSocket extends Socket {
1625
1726 private final String socketFileName ;
1827
19- private RandomAccessFile file ;
20-
21- private InputStream is ;
22-
23- private OutputStream os ;
28+ private AsynchronousFileByteChannel channel ;
2429
2530 NamedPipeSocket (String socketFileName ) {
2631 this .socketFileName = socketFileName ;
2732 }
2833
2934 @ Override
3035 public void close () throws IOException {
31- if (file != null ) {
32- file .close ();
33- file = null ;
36+ if (channel != null ) {
37+ channel .close ();
3438 }
3539 }
3640
3741 @ Override
38- public void connect (SocketAddress endpoint ) {
42+ public void connect (SocketAddress endpoint ) throws IOException {
3943 connect (endpoint , 0 );
4044 }
4145
4246 @ Override
43- public void connect (SocketAddress endpoint , int timeout ) {
47+ public void connect (SocketAddress endpoint , int timeout ) throws IOException {
4448 long startedAt = System .currentTimeMillis ();
4549 timeout = Math .max (timeout , 10_000 );
4650 while (true ) {
4751 try {
48- file = new RandomAccessFile (socketFileName , "rw" );
52+ channel = new AsynchronousFileByteChannel (
53+ AsynchronousFileChannel .open (
54+ Paths .get (socketFileName ),
55+ StandardOpenOption .READ ,
56+ StandardOpenOption .WRITE
57+ )
58+ );
4959 break ;
50- } catch (FileNotFoundException e ) {
60+ } catch (NoSuchFileException e ) {
5161 if (System .currentTimeMillis () - startedAt >= timeout ) {
5262 throw new RuntimeException (e );
5363 } else {
5464 Kernel32 .INSTANCE .WaitNamedPipe (socketFileName , 100 );
5565 }
5666 }
5767 }
58-
59- is = new InputStream () {
60- @ Override
61- public int read (byte [] bytes , int off , int len ) throws IOException {
62- return file .read (bytes , off , len );
63- }
64-
65- @ Override
66- public int read () throws IOException {
67- return file .read ();
68- }
69-
70- @ Override
71- public int read (byte [] bytes ) throws IOException {
72- return file .read (bytes );
73- }
74- };
75-
76- os = new OutputStream () {
77- @ Override
78- public void write (byte [] bytes , int off , int len ) throws IOException {
79- file .write (bytes , off , len );
80- }
81-
82- @ Override
83- public void write (int value ) throws IOException {
84- file .write (value );
85- }
86-
87- @ Override
88- public void write (byte [] bytes ) throws IOException {
89- file .write (bytes );
90- }
91- };
9268 }
9369
9470 @ Override
9571 public InputStream getInputStream () {
96- return is ;
72+ return Channels . newInputStream ( channel ) ;
9773 }
9874
9975 @ Override
10076 public OutputStream getOutputStream () {
101- return os ;
77+ return Channels . newOutputStream ( channel ) ;
10278 }
10379
10480 interface Kernel32 extends StdCallLibrary {
@@ -108,4 +84,75 @@ interface Kernel32 extends StdCallLibrary {
10884 @ SuppressWarnings ("checkstyle:methodname" )
10985 boolean WaitNamedPipe (String lpNamedPipeName , int nTimeOut );
11086 }
87+
88+ private static class AsynchronousFileByteChannel implements AsynchronousByteChannel {
89+ private final AsynchronousFileChannel fileChannel ;
90+
91+ AsynchronousFileByteChannel (AsynchronousFileChannel fileChannel ) {
92+ this .fileChannel = fileChannel ;
93+ }
94+
95+ @ Override
96+ public <A > void read (ByteBuffer dst , A attachment , CompletionHandler <Integer , ? super A > handler ) {
97+ fileChannel .read (dst , 0 , attachment , new CompletionHandler <Integer , A >() {
98+ @ Override
99+ public void completed (Integer read , A attachment ) {
100+ handler .completed (read > 0 ? read : -1 , attachment );
101+ }
102+
103+ @ Override
104+ public void failed (Throwable exc , A attachment ) {
105+ if (exc instanceof AsynchronousCloseException ) {
106+ handler .completed (-1 , attachment );
107+ return ;
108+ }
109+ handler .failed (exc , attachment );
110+ }
111+ });
112+ }
113+
114+ @ Override
115+ public Future <Integer > read (ByteBuffer dst ) {
116+ CompletableFutureHandler future = new CompletableFutureHandler ();
117+ fileChannel .read (dst , 0 , null , future );
118+ return future ;
119+ }
120+
121+ @ Override
122+ public <A > void write (ByteBuffer src , A attachment , CompletionHandler <Integer , ? super A > handler ) {
123+ fileChannel .write (src , 0 , attachment , handler );
124+ }
125+
126+ @ Override
127+ public Future <Integer > write (ByteBuffer src ) {
128+ return fileChannel .write (src , 0 );
129+ }
130+
131+ @ Override
132+ public void close () throws IOException {
133+ fileChannel .close ();
134+ }
135+
136+ @ Override
137+ public boolean isOpen () {
138+ return fileChannel .isOpen ();
139+ }
140+
141+ private static class CompletableFutureHandler extends CompletableFuture <Integer > implements CompletionHandler <Integer , Object > {
142+
143+ @ Override
144+ public void completed (Integer read , Object attachment ) {
145+ complete (read > 0 ? read : -1 );
146+ }
147+
148+ @ Override
149+ public void failed (Throwable exc , Object attachment ) {
150+ if (exc instanceof AsynchronousCloseException ) {
151+ complete (-1 );
152+ return ;
153+ }
154+ completeExceptionally (exc );
155+ }
156+ }
157+ }
111158}
0 commit comments