View Javadoc

    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 14:54:07 +0100 (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 }