View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the 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 io.netty.channel;
17  
18  import io.netty.bootstrap.Bootstrap;
19  import io.netty.bootstrap.ServerBootstrap;
20  import io.netty.channel.ChannelHandler.Sharable;
21  import io.netty.util.internal.logging.InternalLogger;
22  import io.netty.util.internal.logging.InternalLoggerFactory;
23  
24  /**
25   * A special {@link ChannelHandler} which offers an easy way to initialize a {@link Channel} once it was
26   * registered to its {@link EventLoop}.
27   *
28   * Implementations are most often used in the context of {@link Bootstrap#handler(ChannelHandler)} ,
29   * {@link ServerBootstrap#handler(ChannelHandler)} and {@link ServerBootstrap#childHandler(ChannelHandler)} to
30   * setup the {@link ChannelPipeline} of a {@link Channel}.
31   *
32   * <pre>
33   *
34   * public class MyChannelInitializer extends {@link ChannelInitializer} {
35   *     public void initChannel({@link Channel} channel) {
36   *         channel.pipeline().addLast("myHandler", new MyHandler());
37   *     }
38   * }
39   *
40   * {@link ServerBootstrap} bootstrap = ...;
41   * ...
42   * bootstrap.childHandler(new MyChannelInitializer());
43   * ...
44   * </pre>
45   * Be aware that this class is marked as {@link Sharable} and so the implementation must be safe to be re-used.
46   *
47   * @param <C>   A sub-type of {@link Channel}
48   */
49  @Sharable
50  public abstract class ChannelInitializer<C extends Channel> extends ChannelHandlerAdapter {
51  
52      private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelInitializer.class);
53  
54      /**
55       * This method will be called once the {@link Channel} was registered. After the method returns this instance
56       * will be removed from the {@link ChannelPipeline} of the {@link Channel}.
57       *
58       * @param ch            the {@link Channel} which was registered.
59       * @throws Exception    is thrown if an error occurs. In that case the {@link Channel} will be closed.
60       */
61      protected abstract void initChannel(C ch) throws Exception;
62  
63      @Override
64      @SuppressWarnings("unchecked")
65      public final void channelRegistered(ChannelHandlerContext ctx) throws Exception {
66          ChannelPipeline pipeline = ctx.pipeline();
67          boolean success = false;
68          try {
69              initChannel((C) ctx.channel());
70              pipeline.remove(this);
71              ctx.fireChannelRegistered();
72              success = true;
73          } catch (Throwable t) {
74              logger.warn("Failed to initialize a channel. Closing: " + ctx.channel(), t);
75          } finally {
76              if (pipeline.context(this) != null) {
77                  pipeline.remove(this);
78              }
79              if (!success) {
80                  ctx.close();
81              }
82          }
83      }
84  }