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