查看本类的 API文档回源码主页即时通讯网 - 即时通讯开发者社区!
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.mina.common;
21  
22  import java.net.SocketAddress;
23  
24  import org.apache.mina.filter.ReferenceCountingIoFilter;
25  
26  /**
27   * A filter which intercepts {@link IoHandler} events like Servlet
28   * filters.  Filters can be used for these purposes:
29   * <ul>
30   *   <li>Event logging,</li>
31   *   <li>Performance measurement,</li>
32   *   <li>Authorization,</li>
33   *   <li>Overload control,</li>
34   *   <li>Message transformation (e.g. encryption and decryption, ...),</li>
35   *   <li>and many more.</li>
36   * </ul>
37   * <p>
38   * <strong>Please NEVER implement your filters to wrap
39   * {@link IoSession}s.</strong> Users can cache the reference to the
40   * session, which might malfunction if any filters are added or removed later.
41   * 
42   * <h3>The Life Cycle</h3>
43   * {@link IoFilter}s are activated only when they are inside {@link IoFilterChain}.
44   * <p>
45   * When you add an {@link IoFilter} to an {@link IoFilterChain}:
46   * <ol>
47   *   <li>{@link #init()} is invoked by {@link ReferenceCountingIoFilter} if
48   *       the filter is added at the first time.</li>
49   *   <li>{@link #onPreAdd(IoFilterChain, String, NextFilter)} is invoked to notify
50   *       that the filter will be added to the chain.</li>
51   *   <li>The filter is added to the chain, and all events and I/O requests
52   *       pass through the filter from now.</li>
53   *   <li>{@link #onPostAdd(IoFilterChain, String, NextFilter)} is invoked to notify
54   *       that the filter is added to the chain.</li>
55   *   <li>The filter is removed from the chain if {@link #onPostAdd(IoFilterChain, String, org.apache.mina.common.IoFilter.NextFilter)}
56   *       threw an exception.  {@link #destroy()} is also invoked by
57   *       {@link ReferenceCountingIoFilter} if the filter is the last filter which
58   *       was added to {@link IoFilterChain}s.</li>
59   * </ol>
60   * <p>
61   * When you remove an {@link IoFilter} from an {@link IoFilterChain}:
62   * <ol>
63   *   <li>{@link #onPreRemove(IoFilterChain, String, NextFilter)} is invoked to
64   *       notify that the filter will be removed from the chain.</li>
65   *   <li>The filter is removed from the chain, and any events and I/O requests
66   *       don't pass through the filter from now.</li>
67   *   <li>{@link #onPostRemove(IoFilterChain, String, NextFilter)} is invoked to
68   *       notify that the filter is removed from the chain.</li>
69   *   <li>{@link #destroy()} is invoked by {@link ReferenceCountingIoFilter} if
70   *       the removed filter was the last one.</li>
71   * </ol>      
72   * 
73   * @author The Apache Directory Project (mina-dev@directory.apache.org)
74   * @version $Rev: 599822 $, $Date: 2007-11-30 22:54:07 +0900 (Fri, 30 Nov 2007) $
75   * 
76   * @see IoFilterAdapter
77   */
78  public interface IoFilter {
79      /**
80       * Invoked by {@link ReferenceCountingIoFilter} when this filter
81       * is added to a {@link IoFilterChain} at the first time, so you can
82       * initialize shared resources.  Please note that this method is never
83       * called if you don't wrap a filter with {@link ReferenceCountingIoFilter}.
84       */
85      void init() throws Exception;
86  
87      /**
88       * Invoked by {@link ReferenceCountingIoFilter} when this filter
89       * is not used by any {@link IoFilterChain} anymore, so you can destroy
90       * shared resources.  Please note that this method is never called if
91       * you don't wrap a filter with {@link ReferenceCountingIoFilter}.
92       */
93      void destroy() throws Exception;
94  
95      /**
96       * Invoked before this filter is added to the specified <tt>parent</tt>.
97       * Please note that this method can be invoked more than once if
98       * this filter is added to more than one parents.  This method is not
99       * invoked before {@link #init()} is invoked. 
100      *
101      * @param parent the parent who called this method
102      * @param name the name assigned to this filter
103      * @param nextFilter the {@link NextFilter} for this filter.  You can reuse
104      *                   this object until this filter is removed from the chain.
105      */
106     void onPreAdd(IoFilterChain parent, String name, NextFilter nextFilter)
107             throws Exception;
108 
109     /**
110      * Invoked after this filter is added to the specified <tt>parent</tt>.
111      * Please note that this method can be invoked more than once if
112      * this filter is added to more than one parents.  This method is not
113      * invoked before {@link #init()} is invoked. 
114      *
115      * @param parent the parent who called this method
116      * @param name the name assigned to this filter
117      * @param nextFilter the {@link NextFilter} for this filter.  You can reuse
118      *                   this object until this filter is removed from the chain.
119      */
120     void onPostAdd(IoFilterChain parent, String name, NextFilter nextFilter)
121             throws Exception;
122 
123     /**
124      * Invoked before this filter is removed from the specified <tt>parent</tt>.
125      * Please note that this method can be invoked more than once if
126      * this filter is removed from more than one parents.
127      * This method is always invoked before {@link #destroy()} is invoked.
128      *  
129      * @param parent the parent who called this method
130      * @param name the name assigned to this filter
131      * @param nextFilter the {@link NextFilter} for this filter.  You can reuse
132      *                   this object until this filter is removed from the chain.
133      */
134     void onPreRemove(IoFilterChain parent, String name, NextFilter nextFilter)
135             throws Exception;
136 
137     /**
138      * Invoked after this filter is removed from the specified <tt>parent</tt>.
139      * Please note that this method can be invoked more than once if
140      * this filter is removed from more than one parents.
141      * This method is always invoked before {@link #destroy()} is invoked.
142      *  
143      * @param parent the parent who called this method
144      * @param name the name assigned to this filter
145      * @param nextFilter the {@link NextFilter} for this filter.  You can reuse
146      *                   this object until this filter is removed from the chain.
147      */
148     void onPostRemove(IoFilterChain parent, String name, NextFilter nextFilter)
149             throws Exception;
150 
151     /**
152      * Filters {@link IoHandler#sessionCreated(IoSession)} event.
153      */
154     void sessionCreated(NextFilter nextFilter, IoSession session)
155             throws Exception;
156 
157     /**
158      * Filters {@link IoHandler#sessionOpened(IoSession)} event.
159      */
160     void sessionOpened(NextFilter nextFilter, IoSession session)
161             throws Exception;
162 
163     /**
164      * Filters {@link IoHandler#sessionClosed(IoSession)} event.
165      */
166     void sessionClosed(NextFilter nextFilter, IoSession session)
167             throws Exception;
168 
169     /**
170      * Filters {@link IoHandler#sessionIdle(IoSession,IdleStatus)}
171      * event.
172      */
173     void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status)
174             throws Exception;
175 
176     /**
177      * Filters {@link IoHandler#exceptionCaught(IoSession,Throwable)}
178      * event.
179      */
180     void exceptionCaught(NextFilter nextFilter, IoSession session,
181             Throwable cause) throws Exception;
182 
183     /**
184      * Filters {@link IoHandler#messageReceived(IoSession,Object)}
185      * event.
186      */
187     void messageReceived(NextFilter nextFilter, IoSession session,
188             Object message) throws Exception;
189 
190     /**
191      * Filters {@link IoHandler#messageSent(IoSession,Object)}
192      * event.
193      */
194     void messageSent(NextFilter nextFilter, IoSession session, Object message)
195             throws Exception;
196 
197     /**
198      * Filters {@link IoSession#close()} method invocation.
199      */
200     void filterClose(NextFilter nextFilter, IoSession session) throws Exception;
201 
202     /**
203      * Filters {@link IoSession#write(Object)} method invocation.
204      */
205     void filterWrite(NextFilter nextFilter, IoSession session,
206             WriteRequest writeRequest) throws Exception;
207 
208     /**
209      * Represents the next {@link IoFilter} in {@link IoFilterChain}.
210      */
211     public interface NextFilter {
212         /**
213          * Forwards <tt>sessionCreated</tt> event to next filter.
214          */
215         void sessionCreated(IoSession session);
216 
217         /**
218          * Forwards <tt>sessionOpened</tt> event to next filter.
219          */
220         void sessionOpened(IoSession session);
221 
222         /**
223          * Forwards <tt>sessionClosed</tt> event to next filter.
224          */
225         void sessionClosed(IoSession session);
226 
227         /**
228          * Forwards <tt>sessionIdle</tt> event to next filter.
229          */
230         void sessionIdle(IoSession session, IdleStatus status);
231 
232         /**
233          * Forwards <tt>exceptionCaught</tt> event to next filter.
234          */
235         void exceptionCaught(IoSession session, Throwable cause);
236 
237         /**
238          * Forwards <tt>messageReceived</tt> event to next filter.
239          */
240         void messageReceived(IoSession session, Object message);
241 
242         /**
243          * Forwards <tt>messageSent</tt> event to next filter.
244          */
245         void messageSent(IoSession session, Object message);
246 
247         /**
248          * Forwards <tt>filterWrite</tt> event to next filter.
249          */
250         void filterWrite(IoSession session, WriteRequest writeRequest);
251 
252         /**
253          * Forwards <tt>filterClose</tt> event to next filter.
254          */
255         void filterClose(IoSession session);
256     }
257 
258     /**
259      * Represents write request fired by {@link IoSession#write(Object)}.
260      */
261     public static class WriteRequest {
262         private static final WriteFuture UNUSED_FUTURE = new WriteFuture() {
263             public boolean isWritten() {
264                 return false;
265             }
266 
267             public void setWritten(boolean written) {
268             }
269 
270             public IoSession getSession() {
271                 return null;
272             }
273 
274             public void join() {
275             }
276 
277             public boolean join(long timeoutInMillis) {
278                 return true;
279             }
280 
281             public boolean isReady() {
282                 return true;
283             }
284 
285             public void addListener(IoFutureListener listener) {
286                 throw new IllegalStateException(
287                         "You can't add a listener to a dummy future.");
288             }
289 
290             public void removeListener(IoFutureListener listener) {
291                 throw new IllegalStateException(
292                         "You can't add a listener to a dummy future.");
293             }
294 
295             public Object getLock() {
296                 return this;
297             }
298         };
299 
300         private final Object message;
301 
302         private final WriteFuture future;
303 
304         private final SocketAddress destination;
305 
306         /**
307          * Creates a new instance without {@link WriteFuture}.  You'll get
308          * an instance of {@link WriteFuture} even if you called this constructor
309          * because {@link #getFuture()} will return a bogus future.
310          */
311         public WriteRequest(Object message) {
312             this(message, null, null);
313         }
314 
315         /**
316          * Creates a new instance with {@link WriteFuture}.
317          */
318         public WriteRequest(Object message, WriteFuture future) {
319             this(message, future, null);
320         }
321 
322         /**
323          * Creates a new instance.
324          * 
325          * @param message a message to write
326          * @param future a future that needs to be notified when an operation is finished
327          * @param destination the destination of the message.  This property will be
328          *                    ignored unless the transport supports it.
329          */
330         public WriteRequest(Object message, WriteFuture future,
331                 SocketAddress destination) {
332             if (message == null) {
333                 throw new NullPointerException("message");
334             }
335 
336             if (future == null) {
337                 future = UNUSED_FUTURE;
338             }
339 
340             this.message = message;
341             this.future = future;
342             this.destination = destination;
343         }
344 
345         /**
346          * Returns {@link WriteFuture} that is associated with this write request.
347          */
348         public WriteFuture getFuture() {
349             return future;
350         }
351 
352         /**
353          * Returns a message object to be written.
354          */
355         public Object getMessage() {
356             return message;
357         }
358 
359         /**
360          * Returne the destination of this write request.
361          * 
362          * @return <tt>null</tt> for the default destination
363          */
364         public SocketAddress getDestination() {
365             return destination;
366         }
367 
368         @Override
369         public String toString() {
370             return message.toString();
371         }
372     }
373 }