View Javadoc
1   /*
2    * Copyright 2013 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  
17  package io.netty.channel;
18  
19  import io.netty.util.internal.InternalThreadLocalMap;
20  
21  import java.net.SocketAddress;
22  import java.util.Map;
23  import java.util.WeakHashMap;
24  
25  /**
26   * Skelton implementation of a {@link ChannelHandler}.
27   */
28  public class ChannelHandlerAdapter implements ChannelHandler {
29  
30      // Not using volatile because it's used only for a sanity check.
31      boolean added;
32  
33      /**
34       * Return {@code true} if the implementation is {@link Sharable} and so can be added
35       * to different {@link ChannelPipeline}s.
36       */
37      public boolean isSharable() {
38          /**
39           * Cache the result of {@link Sharable} annotation detection to workaround a condition. We use a
40           * {@link ThreadLocal} and {@link WeakHashMap} to eliminate the volatile write/reads. Using different
41           * {@link WeakHashMap} instances per {@link Thread} is good enough for us and the number of
42           * {@link Thread}s are quite limited anyway.
43           *
44           * See <a href="See https://github.com/netty/netty/issues/2289">#2289</a>.
45           */
46          Class<?> clazz = getClass();
47          Map<Class<?>, Boolean> cache = InternalThreadLocalMap.get().handlerSharableCache();
48          Boolean sharable = cache.get(clazz);
49          if (sharable == null) {
50              sharable = clazz.isAnnotationPresent(Sharable.class);
51              cache.put(clazz, sharable);
52          }
53          return sharable;
54      }
55  
56      /**
57       * Do nothing by default, sub-classes may override this method.
58       */
59      @Skip
60      @Override
61      public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
62          // NOOP
63      }
64  
65      /**
66       * Do nothing by default, sub-classes may override this method.
67       */
68      @Skip
69      @Override
70      public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
71          // NOOP
72      }
73  
74      /**
75       * Calls {@link ChannelHandlerContext#fireExceptionCaught(Throwable)} to forward
76       * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
77       *
78       * Sub-classes may override this method to change behavior.
79       */
80      @Skip
81      @Override
82      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
83          ctx.fireExceptionCaught(cause);
84      }
85  
86      /**
87       * Calls {@link ChannelHandlerContext#fireChannelRegistered()} to forward
88       * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
89       *
90       * Sub-classes may override this method to change behavior.
91       */
92      @Skip
93      @Override
94      public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
95          ctx.fireChannelRegistered();
96      }
97  
98      /**
99       * Calls {@link ChannelHandlerContext#fireChannelUnregistered()} to forward
100      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
101      *
102      * Sub-classes may override this method to change behavior.
103      */
104     @Skip
105     @Override
106     public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
107         ctx.fireChannelUnregistered();
108     }
109 
110     /**
111      * Calls {@link ChannelHandlerContext#fireChannelActive()} to forward
112      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
113      *
114      * Sub-classes may override this method to change behavior.
115      */
116     @Skip
117     @Override
118     public void channelActive(ChannelHandlerContext ctx) throws Exception {
119         ctx.fireChannelActive();
120     }
121 
122     /**
123      * Calls {@link ChannelHandlerContext#fireChannelInactive()} to forward
124      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
125      *
126      * Sub-classes may override this method to change behavior.
127      */
128     @Skip
129     @Override
130     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
131         ctx.fireChannelInactive();
132     }
133 
134     /**
135      * Calls {@link ChannelHandlerContext#fireChannelRead(Object)} to forward
136      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
137      *
138      * Sub-classes may override this method to change behavior.
139      */
140     @Skip
141     @Override
142     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
143         ctx.fireChannelRead(msg);
144     }
145 
146     /**
147      * Calls {@link ChannelHandlerContext#fireChannelReadComplete()} to forward
148      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
149      *
150      * Sub-classes may override this method to change behavior.
151      */
152     @Skip
153     @Override
154     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
155         ctx.fireChannelReadComplete();
156     }
157 
158     /**
159      * Calls {@link ChannelHandlerContext#fireUserEventTriggered(Object)} to forward
160      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
161      *
162      * Sub-classes may override this method to change behavior.
163      */
164     @Skip
165     @Override
166     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
167         ctx.fireUserEventTriggered(evt);
168     }
169 
170     /**
171      * Calls {@link ChannelHandlerContext#fireChannelWritabilityChanged()} to forward
172      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
173      *
174      * Sub-classes may override this method to change behavior.
175      */
176     @Skip
177     @Override
178     public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
179         ctx.fireChannelWritabilityChanged();
180     }
181 
182     /**
183      * Calls {@link ChannelHandlerContext#bind(java.net.SocketAddress, ChannelPromise)} to forward
184      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
185      *
186      * Sub-classes may override this method to change behavior.
187      */
188     @Skip
189     @Override
190     public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception {
191         ctx.bind(localAddress, promise);
192     }
193 
194     /**
195      * Calls {@link ChannelHandlerContext#connect(SocketAddress, SocketAddress, ChannelPromise)} to forward
196      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
197      *
198      * Sub-classes may override this method to change behavior.
199      */
200     @Skip
201     @Override
202     public void connect(
203             ChannelHandlerContext ctx,
204             SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) throws Exception {
205         ctx.connect(remoteAddress, localAddress, promise);
206     }
207 
208     /**
209      * Calls {@link ChannelHandlerContext#disconnect(ChannelPromise)} to forward
210      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
211      *
212      * Sub-classes may override this method to change behavior.
213      */
214     @Skip
215     @Override
216     public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
217         ctx.disconnect(promise);
218     }
219 
220     /**
221      * Calls {@link ChannelHandlerContext#close(ChannelPromise)} to forward
222      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
223      *
224      * Sub-classes may override this method to change behavior.
225      */
226     @Skip
227     @Override
228     public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
229         ctx.close(promise);
230     }
231 
232     /**
233      * Calls {@link ChannelHandlerContext#deregister(ChannelPromise)} to forward
234      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
235      *
236      * Sub-classes may override this method to change behavior.
237      */
238     @Skip
239     @Override
240     public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
241         ctx.deregister(promise);
242     }
243 
244     /**
245      * Calls {@link ChannelHandlerContext#read()} to forward
246      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
247      *
248      * Sub-classes may override this method to change behavior.
249      */
250     @Skip
251     @Override
252     public void read(ChannelHandlerContext ctx) throws Exception {
253         ctx.read();
254     }
255 
256     /**
257      * Calls {@link ChannelHandlerContext#write(Object)} to forward
258      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
259      *
260      * Sub-classes may override this method to change behavior.
261      */
262     @Skip
263     @Override
264     public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
265         ctx.write(msg, promise);
266     }
267 
268     /**
269      * Calls {@link ChannelHandlerContext#flush()} to forward
270      * to the next {@link ChannelHandler} in the {@link ChannelPipeline}.
271      *
272      * Sub-classes may override this method to change behavior.
273      */
274     @Skip
275     @Override
276     public void flush(ChannelHandlerContext ctx) throws Exception {
277         ctx.flush();
278     }
279 }