1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.channel;
17
18 import java.net.SocketAddress;
19 import java.util.concurrent.ConcurrentMap;
20
21 import org.jboss.netty.util.internal.ConcurrentHashMap;
22
23
24
25
26
27
28
29
30
31
32 public abstract class AbstractChannel implements Channel {
33
34 static final ConcurrentMap<Integer, Channel> allChannels = new ConcurrentHashMap<Integer, Channel>();
35
36 private static Integer allocateId(Channel channel) {
37 Integer id = Integer.valueOf(System.identityHashCode(channel));
38 for (;;) {
39
40
41 if (allChannels.putIfAbsent(id, channel) == null) {
42
43 return id;
44 } else {
45
46 id = Integer.valueOf(id.intValue() + 1);
47 }
48 }
49 }
50
51 private final Integer id;
52 private final Channel parent;
53 private final ChannelFactory factory;
54 private final ChannelPipeline pipeline;
55 private final ChannelFuture succeededFuture = new SucceededChannelFuture(this);
56 private final ChannelCloseFuture closeFuture = new ChannelCloseFuture();
57 private volatile int interestOps = OP_READ;
58
59
60 private boolean strValConnected;
61 private String strVal;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 protected AbstractChannel(
77 Channel parent, ChannelFactory factory,
78 ChannelPipeline pipeline, ChannelSink sink) {
79
80 this.parent = parent;
81 this.factory = factory;
82 this.pipeline = pipeline;
83
84 id = allocateId(this);
85
86 pipeline.attach(this, sink);
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 protected AbstractChannel(
104 Integer id,
105 Channel parent, ChannelFactory factory,
106 ChannelPipeline pipeline, ChannelSink sink) {
107
108 this.id = id;
109 this.parent = parent;
110 this.factory = factory;
111 this.pipeline = pipeline;
112 pipeline.attach(this, sink);
113 }
114
115 public final Integer getId() {
116 return id;
117 }
118
119 public Channel getParent() {
120 return parent;
121 }
122
123 public ChannelFactory getFactory() {
124 return factory;
125 }
126
127 public ChannelPipeline getPipeline() {
128 return pipeline;
129 }
130
131
132
133
134 protected ChannelFuture getSucceededFuture() {
135 return succeededFuture;
136 }
137
138
139
140
141
142 protected ChannelFuture getUnsupportedOperationFuture() {
143 return new FailedChannelFuture(this, new UnsupportedOperationException());
144 }
145
146
147
148
149
150 @Override
151 public final int hashCode() {
152 return System.identityHashCode(this);
153 }
154
155
156
157
158
159 @Override
160 public final boolean equals(Object o) {
161 return this == o;
162 }
163
164
165
166
167 public final int compareTo(Channel o) {
168 return getId().compareTo(o.getId());
169 }
170
171 public boolean isOpen() {
172 return !closeFuture.isDone();
173 }
174
175
176
177
178
179
180
181
182
183 protected boolean setClosed() {
184
185
186 allChannels.remove(id);
187
188 return closeFuture.setClosed();
189 }
190
191 public ChannelFuture bind(SocketAddress localAddress) {
192 return Channels.bind(this, localAddress);
193 }
194
195 public ChannelFuture unbind() {
196 return Channels.unbind(this);
197 }
198
199 public ChannelFuture close() {
200 ChannelFuture returnedCloseFuture = Channels.close(this);
201 assert closeFuture == returnedCloseFuture;
202 return closeFuture;
203 }
204
205 public ChannelFuture getCloseFuture() {
206 return closeFuture;
207 }
208
209 public ChannelFuture connect(SocketAddress remoteAddress) {
210 return Channels.connect(this, remoteAddress);
211 }
212
213 public ChannelFuture disconnect() {
214 return Channels.disconnect(this);
215 }
216
217 public int getInterestOps() {
218 return interestOps;
219 }
220
221 public ChannelFuture setInterestOps(int interestOps) {
222 return Channels.setInterestOps(this, interestOps);
223 }
224
225
226
227
228
229
230 protected void setInterestOpsNow(int interestOps) {
231 this.interestOps = interestOps;
232 }
233
234 public boolean isReadable() {
235 return (getInterestOps() & OP_READ) != 0;
236 }
237
238 public boolean isWritable() {
239 return (getInterestOps() & OP_WRITE) == 0;
240 }
241
242 public ChannelFuture setReadable(boolean readable) {
243 if (readable) {
244 return setInterestOps(getInterestOps() | OP_READ);
245 } else {
246 return setInterestOps(getInterestOps() & ~OP_READ);
247 }
248 }
249
250 public ChannelFuture write(Object message) {
251 return Channels.write(this, message);
252 }
253
254 public ChannelFuture write(Object message, SocketAddress remoteAddress) {
255 return Channels.write(this, message, remoteAddress);
256 }
257
258
259
260
261
262
263
264 @Override
265 public String toString() {
266 boolean connected = isConnected();
267 if (strValConnected == connected && strVal != null) {
268 return strVal;
269 }
270
271 StringBuilder buf = new StringBuilder(128);
272 buf.append("[id: 0x");
273 buf.append(getIdString());
274
275 SocketAddress localAddress = getLocalAddress();
276 SocketAddress remoteAddress = getRemoteAddress();
277 if (remoteAddress != null) {
278 buf.append(", ");
279 if (getParent() == null) {
280 buf.append(localAddress);
281 buf.append(connected? " => " : " :> ");
282 buf.append(remoteAddress);
283 } else {
284 buf.append(remoteAddress);
285 buf.append(connected? " => " : " :> ");
286 buf.append(localAddress);
287 }
288 } else if (localAddress != null) {
289 buf.append(", ");
290 buf.append(localAddress);
291 }
292
293 buf.append(']');
294
295 String strVal = buf.toString();
296 this.strVal = strVal;
297 strValConnected = connected;
298 return strVal;
299 }
300
301 private String getIdString() {
302 String answer = Integer.toHexString(id.intValue());
303 switch (answer.length()) {
304 case 0:
305 answer = "00000000";
306 break;
307 case 1:
308 answer = "0000000" + answer;
309 break;
310 case 2:
311 answer = "000000" + answer;
312 break;
313 case 3:
314 answer = "00000" + answer;
315 break;
316 case 4:
317 answer = "0000" + answer;
318 break;
319 case 5:
320 answer = "000" + answer;
321 break;
322 case 6:
323 answer = "00" + answer;
324 break;
325 case 7:
326 answer = "0" + answer;
327 break;
328 }
329 return answer;
330 }
331
332 private final class ChannelCloseFuture extends DefaultChannelFuture {
333
334 public ChannelCloseFuture() {
335 super(AbstractChannel.this, false);
336 }
337
338 @Override
339 public boolean setSuccess() {
340
341 return false;
342 }
343
344 @Override
345 public boolean setFailure(Throwable cause) {
346
347 return false;
348 }
349
350 boolean setClosed() {
351 return super.setSuccess();
352 }
353 }
354 }