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.ThreadSafe;
36 import org.apache.http.nio.reactor.IOSession;
37 import org.apache.http.nio.reactor.SessionRequest;
38 import org.apache.http.nio.reactor.SessionRequestCallback;
39
40
41
42
43
44
45 @ThreadSafe
46 public class SessionRequestImpl implements SessionRequest {
47
48 private volatile boolean completed;
49 private volatile SelectionKey key;
50
51 private final SocketAddress remoteAddress;
52 private final SocketAddress localAddress;
53 private final Object attachment;
54 private final SessionRequestCallback callback;
55
56 private volatile int connectTimeout;
57 private volatile IOSession session = null;
58 private volatile IOException exception = null;
59
60 public SessionRequestImpl(
61 final SocketAddress remoteAddress,
62 final SocketAddress localAddress,
63 final Object attachment,
64 final SessionRequestCallback callback) {
65 super();
66 if (remoteAddress == null) {
67 throw new IllegalArgumentException("Remote address may not be null");
68 }
69 this.remoteAddress = remoteAddress;
70 this.localAddress = localAddress;
71 this.attachment = attachment;
72 this.callback = callback;
73 this.connectTimeout = 0;
74 }
75
76 public SocketAddress getRemoteAddress() {
77 return this.remoteAddress;
78 }
79
80 public SocketAddress getLocalAddress() {
81 return this.localAddress;
82 }
83
84 public Object getAttachment() {
85 return this.attachment;
86 }
87
88 public boolean isCompleted() {
89 return this.completed;
90 }
91
92 protected void setKey(final SelectionKey key) {
93 this.key = key;
94 }
95
96 public void waitFor() throws InterruptedException {
97 if (this.completed) {
98 return;
99 }
100 synchronized (this) {
101 while (!this.completed) {
102 wait();
103 }
104 }
105 }
106
107 public IOSession getSession() {
108 synchronized (this) {
109 return this.session;
110 }
111 }
112
113 public IOException getException() {
114 synchronized (this) {
115 return this.exception;
116 }
117 }
118
119 public void completed(final IOSession session) {
120 if (session == null) {
121 throw new IllegalArgumentException("Session may not be null");
122 }
123 if (this.completed) {
124 return;
125 }
126 this.completed = true;
127 synchronized (this) {
128 this.session = session;
129 if (this.callback != null) {
130 this.callback.completed(this);
131 }
132 notifyAll();
133 }
134 }
135
136 public void failed(final IOException exception) {
137 if (exception == null) {
138 return;
139 }
140 if (this.completed) {
141 return;
142 }
143 this.completed = true;
144 SelectionKey key = this.key;
145 if (key != null) {
146 key.cancel();
147 Channel channel = key.channel();
148 if (channel.isOpen()) {
149 try {
150 channel.close();
151 } catch (IOException ignore) {}
152 }
153 }
154 synchronized (this) {
155 this.exception = exception;
156 if (this.callback != null) {
157 this.callback.failed(this);
158 }
159 notifyAll();
160 }
161 }
162
163 public void timeout() {
164 if (this.completed) {
165 return;
166 }
167 this.completed = true;
168 SelectionKey key = this.key;
169 if (key != null) {
170 key.cancel();
171 Channel channel = key.channel();
172 if (channel.isOpen()) {
173 try {
174 channel.close();
175 } catch (IOException ignore) {}
176 }
177 }
178 synchronized (this) {
179 if (this.callback != null) {
180 this.callback.timeout(this);
181 }
182 }
183 }
184
185 public int getConnectTimeout() {
186 return this.connectTimeout;
187 }
188
189 public void setConnectTimeout(int timeout) {
190 if (this.connectTimeout != timeout) {
191 this.connectTimeout = timeout;
192 SelectionKey key = this.key;
193 if (key != null) {
194 key.selector().wakeup();
195 }
196 }
197 }
198
199 public void cancel() {
200 if (this.completed) {
201 return;
202 }
203 this.completed = true;
204 SelectionKey key = this.key;
205 if (key != null) {
206 key.cancel();
207 Channel channel = key.channel();
208 if (channel.isOpen()) {
209 try {
210 channel.close();
211 } catch (IOException ignore) {}
212 }
213 }
214 synchronized (this) {
215 if (this.callback != null) {
216 this.callback.cancelled(this);
217 }
218 notifyAll();
219 }
220 }
221
222 }