1 /* 2 * Copyright 2009 Red Hat, Inc. 3 * 4 * Red Hat licenses this file to you under the Apache License, version 2.0 5 * (the "License"); you may not use this file except in compliance with the 6 * License. You may obtain a copy of the License at: 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations 14 * under the License. 15 */ 16 package org.jboss.netty.channel; 17 18 import java.net.SocketAddress; 19 import java.util.Map; 20 21 import org.jboss.netty.util.internal.ConversionUtil; 22 23 24 /** 25 * A helper class which provides various convenience methods related with 26 * {@link Channel}, {@link ChannelHandler}, and {@link ChannelPipeline}. 27 * 28 * <h3>Factory methods</h3> 29 * <p> 30 * It is always recommended to use the factory methods provided by 31 * {@link Channels} rather than calling the constructor of the implementation 32 * types. 33 * <ul> 34 * <li>{@link #pipeline()}</li> 35 * <li>{@link #pipeline(ChannelPipeline)}</li> 36 * <li>{@link #pipelineFactory(ChannelPipeline)}</li> 37 * <li>{@link #succeededFuture(Channel)}</li> 38 * <li>{@link #failedFuture(Channel, Throwable)}</li> 39 * </ul> 40 * 41 * <h3>Upstream and downstream event generation</h3> 42 * <p> 43 * Various event generation methods are provided to simplify the generation of 44 * upstream events and downstream events. It is always recommended to use the 45 * event generation methods provided by {@link Channels} rather than calling 46 * {@link ChannelHandlerContext#sendUpstream(ChannelEvent)} or 47 * {@link ChannelHandlerContext#sendDownstream(ChannelEvent)} by yourself. 48 * 49 * @author <a href="http://www.jboss.org/netty/">The Netty Project</a> 50 * @author <a href="http://gleamynode.net/">Trustin Lee</a> 51 * 52 * @apiviz.landmark 53 * 54 * @version $Rev: 2210 $, $Date: 2010-03-04 08:11:39 +0900 (Thu, 04 Mar 2010) $ 55 */ 56 public class Channels { 57 58 // pipeline factory methods 59 60 /** 61 * Creates a new {@link ChannelPipeline}. 62 */ 63 public static ChannelPipeline pipeline() { 64 return new DefaultChannelPipeline(); 65 } 66 67 /** 68 * Creates a new {@link ChannelPipeline} which contains the specified 69 * {@link ChannelHandler}s. The names of the specified handlers are 70 * generated automatically; the first handler's name is {@code "0"}, 71 * the second handler's name is {@code "1"}, the third handler's name is 72 * {@code "2"}, and so on. 73 */ 74 public static ChannelPipeline pipeline(ChannelHandler... handlers) { 75 if (handlers == null) { 76 throw new NullPointerException("handlers"); 77 } 78 79 ChannelPipeline newPipeline = pipeline(); 80 for (int i = 0; i < handlers.length; i ++) { 81 ChannelHandler h = handlers[i]; 82 if (h == null) { 83 break; 84 } 85 newPipeline.addLast(ConversionUtil.toString(i), h); 86 } 87 return newPipeline; 88 } 89 90 /** 91 * Creates a new {@link ChannelPipeline} which contains the same entries 92 * with the specified {@code pipeline}. Please note that only the names 93 * and the references of the {@link ChannelHandler}s will be copied; a new 94 * {@link ChannelHandler} instance will never be created. 95 */ 96 public static ChannelPipeline pipeline(ChannelPipeline pipeline) { 97 ChannelPipeline newPipeline = pipeline(); 98 for (Map.Entry<String, ChannelHandler> e: pipeline.toMap().entrySet()) { 99 newPipeline.addLast(e.getKey(), e.getValue()); 100 } 101 return newPipeline; 102 } 103 104 /** 105 * Creates a new {@link ChannelPipelineFactory} which creates a new 106 * {@link ChannelPipeline} which contains the same entries with the 107 * specified {@code pipeline}. Please note that only the names and the 108 * references of the {@link ChannelHandler}s will be copied; a new 109 * {@link ChannelHandler} instance will never be created. 110 */ 111 public static ChannelPipelineFactory pipelineFactory( 112 final ChannelPipeline pipeline) { 113 return new ChannelPipelineFactory() { 114 public ChannelPipeline getPipeline() { 115 return pipeline(pipeline); 116 } 117 }; 118 } 119 120 // future factory methods 121 122 /** 123 * Creates a new non-cancellable {@link ChannelFuture} for the specified 124 * {@link Channel}. 125 */ 126 public static ChannelFuture future(Channel channel) { 127 return future(channel, false); 128 } 129 130 /** 131 * Creates a new {@link ChannelFuture} for the specified {@link Channel}. 132 * 133 * @param cancellable {@code true} if and only if the returned future 134 * can be canceled by {@link ChannelFuture#cancel()} 135 */ 136 public static ChannelFuture future(Channel channel, boolean cancellable) { 137 return new DefaultChannelFuture(channel, cancellable); 138 } 139 140 /** 141 * Creates a new {@link ChannelFuture} which is already succeeded for the 142 * specified {@link Channel}. 143 */ 144 public static ChannelFuture succeededFuture(Channel channel) { 145 if (channel instanceof AbstractChannel) { 146 return ((AbstractChannel) channel).getSucceededFuture(); 147 } else { 148 return new SucceededChannelFuture(channel); 149 } 150 } 151 152 /** 153 * Creates a new {@link ChannelFuture} which has failed already for the 154 * specified {@link Channel}. 155 * 156 * @param cause the cause of the failure 157 */ 158 public static ChannelFuture failedFuture(Channel channel, Throwable cause) { 159 return new FailedChannelFuture(channel, cause); 160 } 161 162 // event emission methods 163 164 /** 165 * Sends a {@code "channelOpen"} event to the first 166 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 167 * the specified {@link Channel}. If the specified channel has a parent, 168 * a {@code "childChannelOpen"} event will be sent, too. 169 */ 170 public static void fireChannelOpen(Channel channel) { 171 // Notify the parent handler. 172 if (channel.getParent() != null) { 173 fireChildChannelStateChanged(channel.getParent(), channel); 174 } 175 176 channel.getPipeline().sendUpstream( 177 new UpstreamChannelStateEvent( 178 channel, ChannelState.OPEN, Boolean.TRUE)); 179 } 180 181 /** 182 * Sends a {@code "channelOpen"} event to the 183 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 184 * from the handler associated with the specified 185 * {@link ChannelHandlerContext}. 186 * <p> 187 * Please note that this method does not trigger a 188 * {@code "childChannelOpen"} event unlike {@link #fireChannelOpen(Channel)} 189 * method. 190 */ 191 public static void fireChannelOpen(ChannelHandlerContext ctx) { 192 ctx.sendUpstream(new UpstreamChannelStateEvent( 193 ctx.getChannel(), ChannelState.OPEN, Boolean.TRUE)); 194 } 195 196 /** 197 * Sends a {@code "channelBound"} event to the first 198 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 199 * the specified {@link Channel}. 200 * 201 * @param localAddress 202 * the local address where the specified channel is bound 203 */ 204 public static void fireChannelBound(Channel channel, SocketAddress localAddress) { 205 channel.getPipeline().sendUpstream( 206 new UpstreamChannelStateEvent( 207 channel, ChannelState.BOUND, localAddress)); 208 } 209 210 /** 211 * Sends a {@code "channelBound"} event to the 212 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 213 * from the handler associated with the specified 214 * {@link ChannelHandlerContext}. 215 * 216 * @param localAddress 217 * the local address where the specified channel is bound 218 */ 219 public static void fireChannelBound(ChannelHandlerContext ctx, SocketAddress localAddress) { 220 ctx.sendUpstream(new UpstreamChannelStateEvent( 221 ctx.getChannel(), ChannelState.BOUND, localAddress)); 222 } 223 224 /** 225 * Sends a {@code "channelConnected"} event to the first 226 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 227 * the specified {@link Channel}. 228 * 229 * @param remoteAddress 230 * the remote address where the specified channel is connected 231 */ 232 public static void fireChannelConnected(Channel channel, SocketAddress remoteAddress) { 233 channel.getPipeline().sendUpstream( 234 new UpstreamChannelStateEvent( 235 channel, ChannelState.CONNECTED, remoteAddress)); 236 } 237 238 /** 239 * Sends a {@code "channelConnected"} event to the 240 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 241 * from the handler associated with the specified 242 * {@link ChannelHandlerContext}. 243 * 244 * @param remoteAddress 245 * the remote address where the specified channel is connected 246 */ 247 public static void fireChannelConnected(ChannelHandlerContext ctx, SocketAddress remoteAddress) { 248 249 ctx.sendUpstream(new UpstreamChannelStateEvent( 250 ctx.getChannel(), ChannelState.CONNECTED, remoteAddress)); 251 } 252 253 /** 254 * Sends a {@code "messageReceived"} event to the first 255 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 256 * the specified {@link Channel}. 257 * 258 * @param message the received message 259 */ 260 public static void fireMessageReceived(Channel channel, Object message) { 261 fireMessageReceived(channel, message, null); 262 } 263 264 /** 265 * Sends a {@code "messageReceived"} event to the first 266 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 267 * the specified {@link Channel} belongs. 268 * 269 * @param message the received message 270 * @param remoteAddress the remote address where the received message 271 * came from 272 */ 273 public static void fireMessageReceived(Channel channel, Object message, SocketAddress remoteAddress) { 274 channel.getPipeline().sendUpstream( 275 new UpstreamMessageEvent(channel, message, remoteAddress)); 276 } 277 278 /** 279 * Sends a {@code "messageReceived"} event to the 280 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 281 * from the handler associated with the specified 282 * {@link ChannelHandlerContext}. 283 * 284 * @param message the received message 285 */ 286 public static void fireMessageReceived(ChannelHandlerContext ctx, Object message) { 287 ctx.sendUpstream(new UpstreamMessageEvent(ctx.getChannel(), message, null)); 288 } 289 290 /** 291 * Sends a {@code "messageReceived"} event to the 292 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 293 * from the handler associated with the specified 294 * {@link ChannelHandlerContext}. 295 * 296 * @param message the received message 297 * @param remoteAddress the remote address where the received message 298 * came from 299 */ 300 public static void fireMessageReceived( 301 ChannelHandlerContext ctx, Object message, SocketAddress remoteAddress) { 302 ctx.sendUpstream(new UpstreamMessageEvent( 303 ctx.getChannel(), message, remoteAddress)); 304 } 305 306 /** 307 * Sends a {@code "writeComplete"} event to the first 308 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 309 * the specified {@link Channel}. 310 */ 311 public static void fireWriteComplete(Channel channel, long amount) { 312 if (amount == 0) { 313 return; 314 } 315 316 channel.getPipeline().sendUpstream( 317 new DefaultWriteCompletionEvent(channel, amount)); 318 } 319 320 /** 321 * Sends a {@code "writeComplete"} event to the 322 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 323 * from the handler associated with the specified 324 * {@link ChannelHandlerContext}. 325 */ 326 public static void fireWriteComplete(ChannelHandlerContext ctx, long amount) { 327 ctx.sendUpstream(new DefaultWriteCompletionEvent(ctx.getChannel(), amount)); 328 } 329 /** 330 * Sends a {@code "channelInterestChanged"} event to the first 331 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 332 * the specified {@link Channel}. 333 */ 334 public static void fireChannelInterestChanged(Channel channel) { 335 channel.getPipeline().sendUpstream( 336 new UpstreamChannelStateEvent( 337 channel, ChannelState.INTEREST_OPS, Channel.OP_READ)); 338 } 339 340 /** 341 * Sends a {@code "channelInterestChanged"} event to the 342 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 343 * from the handler associated with the specified 344 * {@link ChannelHandlerContext}. 345 */ 346 public static void fireChannelInterestChanged( 347 ChannelHandlerContext ctx) { 348 349 ctx.sendUpstream( 350 new UpstreamChannelStateEvent( 351 ctx.getChannel(), ChannelState.INTEREST_OPS, Channel.OP_READ)); 352 } 353 354 /** 355 * Sends a {@code "channelDisconnected"} event to the first 356 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 357 * the specified {@link Channel}. 358 */ 359 public static void fireChannelDisconnected(Channel channel) { 360 channel.getPipeline().sendUpstream( 361 new UpstreamChannelStateEvent( 362 channel, ChannelState.CONNECTED, null)); 363 } 364 365 /** 366 * Sends a {@code "channelDisconnected"} event to the 367 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 368 * from the handler associated with the specified 369 * {@link ChannelHandlerContext}. 370 */ 371 public static void fireChannelDisconnected(ChannelHandlerContext ctx) { 372 ctx.sendUpstream(new UpstreamChannelStateEvent( 373 ctx.getChannel(), ChannelState.CONNECTED, null)); 374 } 375 376 /** 377 * Sends a {@code "channelUnbound"} event to the first 378 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 379 * the specified {@link Channel}. 380 */ 381 public static void fireChannelUnbound(Channel channel) { 382 channel.getPipeline().sendUpstream(new UpstreamChannelStateEvent( 383 channel, ChannelState.BOUND, null)); 384 } 385 386 /** 387 * Sends a {@code "channelUnbound"} event to the 388 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 389 * from the handler associated with the specified 390 * {@link ChannelHandlerContext}. 391 */ 392 public static void fireChannelUnbound(ChannelHandlerContext ctx) { 393 394 ctx.sendUpstream(new UpstreamChannelStateEvent( 395 ctx.getChannel(), ChannelState.BOUND, null)); 396 } 397 398 /** 399 * Sends a {@code "channelClosed"} event to the first 400 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 401 * the specified {@link Channel}. 402 */ 403 public static void fireChannelClosed(Channel channel) { 404 channel.getPipeline().sendUpstream( 405 new UpstreamChannelStateEvent( 406 channel, ChannelState.OPEN, Boolean.FALSE)); 407 408 // Notify the parent handler. 409 if (channel.getParent() != null) { 410 fireChildChannelStateChanged(channel.getParent(), channel); 411 } 412 } 413 414 /** 415 * Sends a {@code "channelClosed"} event to the 416 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 417 * from the handler associated with the specified 418 * {@link ChannelHandlerContext}. 419 */ 420 public static void fireChannelClosed(ChannelHandlerContext ctx) { 421 ctx.sendUpstream( 422 new UpstreamChannelStateEvent( 423 ctx.getChannel(), ChannelState.OPEN, Boolean.FALSE)); 424 } 425 426 /** 427 * Sends a {@code "exceptionCaught"} event to the first 428 * {@link ChannelUpstreamHandler} in the {@link ChannelPipeline} of 429 * the specified {@link Channel}. 430 */ 431 public static void fireExceptionCaught(Channel channel, Throwable cause) { 432 channel.getPipeline().sendUpstream( 433 new DefaultExceptionEvent(channel, cause)); 434 } 435 436 /** 437 * Sends a {@code "exceptionCaught"} event to the 438 * {@link ChannelUpstreamHandler} which is placed in the closest upstream 439 * from the handler associated with the specified 440 * {@link ChannelHandlerContext}. 441 */ 442 public static void fireExceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 443 ctx.sendUpstream(new DefaultExceptionEvent(ctx.getChannel(), cause)); 444 } 445 446 private static void fireChildChannelStateChanged( 447 Channel channel, Channel childChannel) { 448 channel.getPipeline().sendUpstream( 449 new DefaultChildChannelStateEvent(channel, childChannel)); 450 } 451 452 /** 453 * Sends a {@code "bind"} request to the last 454 * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of 455 * the specified {@link Channel}. 456 * 457 * @param channel the channel to bind 458 * @param localAddress the local address to bind to 459 * 460 * @return the {@link ChannelFuture} which will be notified when the 461 * bind operation is done 462 */ 463 public static ChannelFuture bind(Channel channel, SocketAddress localAddress) { 464 if (localAddress == null) { 465 throw new NullPointerException("localAddress"); 466 } 467 ChannelFuture future = future(channel); 468 channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent( 469 channel, future, ChannelState.BOUND, localAddress)); 470 return future; 471 } 472 473 /** 474 * Sends a {@code "bind"} request to the 475 * {@link ChannelDownstreamHandler} which is placed in the closest 476 * downstream from the handler associated with the specified 477 * {@link ChannelHandlerContext}. 478 * 479 * @param ctx the context 480 * @param future the future which will be notified when the bind 481 * operation is done 482 * @param localAddress the local address to bind to 483 */ 484 public static void bind( 485 ChannelHandlerContext ctx, ChannelFuture future, SocketAddress localAddress) { 486 if (localAddress == null) { 487 throw new NullPointerException("localAddress"); 488 } 489 ctx.sendDownstream(new DownstreamChannelStateEvent( 490 ctx.getChannel(), future, ChannelState.BOUND, localAddress)); 491 } 492 493 /** 494 * Sends a {@code "unbind"} request to the 495 * {@link ChannelDownstreamHandler} which is placed in the closest 496 * downstream from the handler associated with the specified 497 * {@link ChannelHandlerContext}. 498 * 499 * @param ctx the context 500 * @param future the future which will be notified when the unbind 501 * operation is done 502 */ 503 public static void unbind(ChannelHandlerContext ctx, ChannelFuture future) { 504 ctx.sendDownstream(new DownstreamChannelStateEvent( 505 ctx.getChannel(), future, ChannelState.BOUND, null)); 506 } 507 508 /** 509 * Sends a {@code "unbind"} request to the last 510 * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of 511 * the specified {@link Channel}. 512 * 513 * @param channel the channel to unbind 514 * 515 * @return the {@link ChannelFuture} which will be notified when the 516 * unbind operation is done 517 */ 518 public static ChannelFuture unbind(Channel channel) { 519 ChannelFuture future = future(channel); 520 channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent( 521 channel, future, ChannelState.BOUND, null)); 522 return future; 523 } 524 525 /** 526 * Sends a {@code "connect"} request to the last 527 * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of 528 * the specified {@link Channel}. 529 * 530 * @param channel the channel to attempt a connection 531 * @param remoteAddress the remote address to connect to 532 * 533 * @return the {@link ChannelFuture} which will be notified when the 534 * connection attempt is done 535 */ 536 public static ChannelFuture connect(Channel channel, SocketAddress remoteAddress) { 537 if (remoteAddress == null) { 538 throw new NullPointerException("remoteAddress"); 539 } 540 ChannelFuture future = future(channel, true); 541 channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent( 542 channel, future, ChannelState.CONNECTED, remoteAddress)); 543 return future; 544 } 545 546 /** 547 * Sends a {@code "connect"} request to the 548 * {@link ChannelDownstreamHandler} which is placed in the closest 549 * downstream from the handler associated with the specified 550 * {@link ChannelHandlerContext}. 551 * 552 * @param ctx the context 553 * @param future the future which will be notified when the connection 554 * attempt is done 555 * @param remoteAddress the remote address to connect to 556 */ 557 public static void connect( 558 ChannelHandlerContext ctx, ChannelFuture future, SocketAddress remoteAddress) { 559 if (remoteAddress == null) { 560 throw new NullPointerException("remoteAddress"); 561 } 562 ctx.sendDownstream(new DownstreamChannelStateEvent( 563 ctx.getChannel(), future, ChannelState.CONNECTED, remoteAddress)); 564 } 565 566 /** 567 * Sends a {@code "write"} request to the last 568 * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of 569 * the specified {@link Channel}. 570 * 571 * @param channel the channel to write a message 572 * @param message the message to write to the channel 573 * 574 * @return the {@link ChannelFuture} which will be notified when the 575 * write operation is done 576 */ 577 public static ChannelFuture write(Channel channel, Object message) { 578 return write(channel, message, null); 579 } 580 581 /** 582 * Sends a {@code "write"} request to the 583 * {@link ChannelDownstreamHandler} which is placed in the closest 584 * downstream from the handler associated with the specified 585 * {@link ChannelHandlerContext}. 586 * 587 * @param ctx the context 588 * @param future the future which will be notified when the write 589 * operation is done 590 */ 591 public static void write( 592 ChannelHandlerContext ctx, ChannelFuture future, Object message) { 593 write(ctx, future, message, null); 594 } 595 596 /** 597 * Sends a {@code "write"} request to the last 598 * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of 599 * the specified {@link Channel}. 600 * 601 * @param channel the channel to write a message 602 * @param message the message to write to the channel 603 * @param remoteAddress the destination of the message. 604 * {@code null} to use the default remote address 605 * 606 * @return the {@link ChannelFuture} which will be notified when the 607 * write operation is done 608 */ 609 public static ChannelFuture write(Channel channel, Object message, SocketAddress remoteAddress) { 610 ChannelFuture future = future(channel); 611 channel.getPipeline().sendDownstream( 612 new DownstreamMessageEvent(channel, future, message, remoteAddress)); 613 return future; 614 } 615 616 /** 617 * Sends a {@code "write"} request to the 618 * {@link ChannelDownstreamHandler} which is placed in the closest 619 * downstream from the handler associated with the specified 620 * {@link ChannelHandlerContext}. 621 * 622 * @param ctx the context 623 * @param future the future which will be notified when the write 624 * operation is done 625 * @param message the message to write to the channel 626 * @param remoteAddress the destination of the message. 627 * {@code null} to use the default remote address. 628 */ 629 public static void write( 630 ChannelHandlerContext ctx, ChannelFuture future, 631 Object message, SocketAddress remoteAddress) { 632 ctx.sendDownstream( 633 new DownstreamMessageEvent(ctx.getChannel(), future, message, remoteAddress)); 634 } 635 636 /** 637 * Sends a {@code "setInterestOps"} request to the last 638 * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of 639 * the specified {@link Channel}. 640 * 641 * @param channel the channel to change its interestOps 642 * @param interestOps the new interestOps 643 * 644 * @return the {@link ChannelFuture} which will be notified when the 645 * interestOps is changed 646 */ 647 public static ChannelFuture setInterestOps(Channel channel, int interestOps) { 648 validateInterestOps(interestOps); 649 interestOps = filterDownstreamInterestOps(interestOps); 650 651 ChannelFuture future = future(channel); 652 channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent( 653 channel, future, ChannelState.INTEREST_OPS, Integer.valueOf(interestOps))); 654 return future; 655 } 656 657 /** 658 * Sends a {@code "setInterestOps"} request to the 659 * {@link ChannelDownstreamHandler} which is placed in the closest 660 * downstream from the handler associated with the specified 661 * {@link ChannelHandlerContext}. 662 * 663 * @param ctx the context 664 * @param future the future which will be notified when the interestOps is 665 * changed. 666 */ 667 public static void setInterestOps( 668 ChannelHandlerContext ctx, ChannelFuture future, int interestOps) { 669 validateInterestOps(interestOps); 670 interestOps = filterDownstreamInterestOps(interestOps); 671 672 ctx.sendDownstream( 673 new DownstreamChannelStateEvent( 674 ctx.getChannel(), future, ChannelState.INTEREST_OPS, 675 Integer.valueOf(interestOps))); 676 } 677 678 /** 679 * Sends a {@code "disconnect"} request to the last 680 * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of 681 * the specified {@link Channel}. 682 * 683 * @param channel the channel to disconnect 684 * 685 * @return the {@link ChannelFuture} which will be notified on disconnection 686 */ 687 public static ChannelFuture disconnect(Channel channel) { 688 ChannelFuture future = future(channel); 689 channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent( 690 channel, future, ChannelState.CONNECTED, null)); 691 return future; 692 } 693 694 /** 695 * Sends a {@code "disconnect"} request to the 696 * {@link ChannelDownstreamHandler} which is placed in the closest 697 * downstream from the handler associated with the specified 698 * {@link ChannelHandlerContext}. 699 * 700 * @param ctx the context 701 * @param future the future which will be notified on disconnection 702 */ 703 public static void disconnect( 704 ChannelHandlerContext ctx, ChannelFuture future) { 705 ctx.sendDownstream(new DownstreamChannelStateEvent( 706 ctx.getChannel(), future, ChannelState.CONNECTED, null)); 707 } 708 709 /** 710 * Sends a {@code "close"} request to the last 711 * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of 712 * the specified {@link Channel}. 713 * 714 * @param channel the channel to close 715 * 716 * @return the {@link ChannelFuture} which will be notified on closure 717 */ 718 public static ChannelFuture close(Channel channel) { 719 ChannelFuture future = channel.getCloseFuture(); 720 channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent( 721 channel, future, ChannelState.OPEN, Boolean.FALSE)); 722 return future; 723 } 724 725 /** 726 * Sends a {@code "close"} request to the 727 * {@link ChannelDownstreamHandler} which is placed in the closest 728 * downstream from the handler associated with the specified 729 * {@link ChannelHandlerContext}. 730 * 731 * @param ctx the context 732 * @param future the future which will be notified on closure 733 */ 734 public static void close( 735 ChannelHandlerContext ctx, ChannelFuture future) { 736 ctx.sendDownstream(new DownstreamChannelStateEvent( 737 ctx.getChannel(), future, ChannelState.OPEN, Boolean.FALSE)); 738 } 739 740 private static void validateInterestOps(int interestOps) { 741 switch (interestOps) { 742 case Channel.OP_NONE: 743 case Channel.OP_READ: 744 case Channel.OP_WRITE: 745 case Channel.OP_READ_WRITE: 746 break; 747 default: 748 throw new IllegalArgumentException( 749 "Invalid interestOps: " + interestOps); 750 } 751 } 752 753 private static int filterDownstreamInterestOps(int interestOps) { 754 return interestOps & ~Channel.OP_WRITE; 755 } 756 757 private Channels() { 758 // Unused 759 } 760 }