1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.impl.nio.reactor;
29
30 import java.io.IOException;
31 import java.net.SocketAddress;
32 import java.nio.channels.Channel;
33 import java.nio.channels.SelectionKey;
34
35 import org.apache.http.annotation.ThreadingBehavior;
36 import org.apache.http.annotation.Contract;
37 import org.apache.http.nio.reactor.ListenerEndpoint;
38 import org.apache.http.util.Args;
39
40
41
42
43
44
45 @Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL)
46 public class ListenerEndpointImpl implements ListenerEndpoint {
47
48 private volatile boolean completed;
49 private volatile boolean closed;
50 private volatile SelectionKey key;
51 private volatile SocketAddress address;
52 private volatile IOException exception;
53
54 private final ListenerEndpointClosedCallback callback;
55
56 public ListenerEndpointImpl(
57 final SocketAddress address,
58 final ListenerEndpointClosedCallback callback) {
59 super();
60 Args.notNull(address, "Address");
61 this.address = address;
62 this.callback = callback;
63 }
64
65 @Override
66 public SocketAddress getAddress() {
67 return this.address;
68 }
69
70 public boolean isCompleted() {
71 return this.completed;
72 }
73
74 @Override
75 public IOException getException() {
76 return this.exception;
77 }
78
79 @Override
80 public void waitFor() throws InterruptedException {
81 if (this.completed) {
82 return;
83 }
84 synchronized (this) {
85 while (!this.completed) {
86 wait();
87 }
88 }
89 }
90
91 public void completed(final SocketAddress address) {
92 Args.notNull(address, "Address");
93 if (this.completed) {
94 return;
95 }
96 this.completed = true;
97 synchronized (this) {
98 this.address = address;
99 notifyAll();
100 }
101 }
102
103 public void failed(final IOException exception) {
104 if (exception == null) {
105 return;
106 }
107 if (this.completed) {
108 return;
109 }
110 this.completed = true;
111 synchronized (this) {
112 this.exception = exception;
113 notifyAll();
114 }
115 }
116
117 public void cancel() {
118 if (this.completed) {
119 return;
120 }
121 this.completed = true;
122 this.closed = true;
123 synchronized (this) {
124 notifyAll();
125 }
126 }
127
128 protected void setKey(final SelectionKey key) {
129 this.key = key;
130 }
131
132 @Override
133 public boolean isClosed() {
134 return this.closed || (this.key != null && !this.key.isValid());
135 }
136
137 @Override
138 public void close() {
139 if (this.closed) {
140 return;
141 }
142 this.completed = true;
143 this.closed = true;
144 if (this.key != null) {
145 this.key.cancel();
146 final Channel channel = this.key.channel();
147 try {
148 channel.close();
149 } catch (final IOException ignore) {}
150 }
151 if (this.callback != null) {
152 this.callback.endpointClosed(this);
153 }
154 synchronized (this) {
155 notifyAll();
156 }
157 }
158
159 @Override
160 public String toString() {
161 return "[address=" + address + ", key=" + key + ", closed=" + closed + ", completed="
162 + completed + ", exception=" + exception + ", callback=" + callback + "]";
163 }
164
165 }