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.util.ArrayList;
    23  import java.util.Collections;
    24  import java.util.Iterator;
    25  import java.util.List;
    26  import java.util.ListIterator;
    27  import java.util.concurrent.CopyOnWriteArrayList;
    28
    29  import org.apache.mina.common.IoFilter.NextFilter;
    30  import org.apache.mina.common.IoFilterChain.Entry;
    31
    32  /**
    33   * The default implementation of {@link IoFilterChainBuilder} which is useful
    34   * in most cases.  {@link DefaultIoFilterChainBuilder} has an identical interface
    35   * with {@link IoFilter}; it contains a list of {@link IoFilter}s that you can
    36   * modify. The {@link IoFilter}s which are added to this builder will be appended
    37   * to the {@link IoFilterChain} when {@link #buildFilterChain(IoFilterChain)} is
    38   * invoked.
    39   * <p>
    40   * However, the identical interface doesn't mean that it behaves in an exactly
    41   * same way with {@link IoFilterChain}.  {@link DefaultIoFilterChainBuilder}
    42   * doesn't manage the life cycle of the {@link IoFilter}s at all, and the
    43   * existing {@link IoSession}s won't get affected by the changes in this builder.
    44   * {@link IoFilterChainBuilder}s affect only newly created {@link IoSession}s.
    45   *
    46   * <pre>
    47   * IoAcceptor acceptor = ...;
    48   * DefaultIoFilterChainBuilder builder = acceptor.getFilterChain();
    49   * builder.addLast( "myFilter", new MyFilter() );
    50   * ...
    51   * </pre>
    52   *
    53   * @author The Apache Directory Project (mina-dev@directory.apache.org)
    54   * @version $Rev: 562335 $, $Date: 2007-08-03 14:28:02 +0900 (Fri, 03 Aug 2007) $
    55   */
    56  public class DefaultIoFilterChainBuilder implements IoFilterChainBuilder,
    57          Cloneable {
    58      private final List<Entry> entries;
    59
    60      /**
    61       * Creates a new instance with an empty filter list.
    62       */
    63      public DefaultIoFilterChainBuilder() {
    64          entries = new CopyOnWriteArrayList<Entry>();
    65      }
    66
    67      /**
    68       * @see IoFilterChain#getEntry(String)
    69       */
    70      public Entry getEntry(String name) {
    71          for (Entry e: entries) {
    72              if (e.getName().equals(name)) {
    73                  return e;
    74              }
    75          }
    76
    77          return null;
    78      }
    79
    80      /**
    81       * @see IoFilterChain#get(String)
    82       */
    83      public IoFilter get(String name) {
    84          Entry e = getEntry(name);
    85          if (e == null) {
    86              return null;
    87          }
    88
    89          return e.getFilter();
    90      }
    91
    92      /**
    93       * @see IoFilterChain#getAll()
    94       */
    95      public List<Entry> getAll() {
    96          return new ArrayList<Entry>(entries);
    97      }
    98
    99      /**
    100      * @see IoFilterChain#getAllReversed()
    101      */
    102     public List<Entry> getAllReversed() {
    103         List<Entry> result = getAll();
    104         Collections.reverse(result);
    105         return result;
    106     }
    107
    108     /**
    109      * @see IoFilterChain#contains(String)
    110      */
    111     public boolean contains(String name) {
    112         return getEntry(name) != null;
    113     }
    114
    115     /**
    116      * @see IoFilterChain#contains(IoFilter)
    117      */
    118     public boolean contains(IoFilter filter) {
    119         for (Iterator i = entries.iterator(); i.hasNext();) {
    120             Entry e = (Entry) i.next();
    121             if (e.getFilter() == filter) {
    122                 return true;
    123             }
    124         }
    125
    126         return false;
    127     }
    128
    129     /**
    130      * @see IoFilterChain#contains(Class)
    131      */
    132     public boolean contains(Class<? extends IoFilter> filterType) {
    133         for (Iterator i = entries.iterator(); i.hasNext();) {
    134             Entry e = (Entry) i.next();
    135             if (filterType.isAssignableFrom(e.getFilter().getClass())) {
    136                 return true;
    137             }
    138         }
    139
    140         return false;
    141     }
    142
    143     /**
    144      * @see IoFilterChain#addFirst(String, IoFilter)
    145      */
    146     public synchronized void addFirst(String name, IoFilter filter) {
    147         register(0, new EntryImpl(name, filter));
    148     }
    149
    150     /**
    151      * @see IoFilterChain#addLast(String, IoFilter)
    152      */
    153     public synchronized void addLast(String name, IoFilter filter) {
    154         register(entries.size(), new EntryImpl(name, filter));
    155     }
    156
    157     /**
    158      * @see IoFilterChain#addBefore(String, String, IoFilter)
    159      */
    160     public synchronized void addBefore(String baseName, String name,
    161             IoFilter filter) {
    162         checkBaseName(baseName);
    163
    164         for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
    165             Entry base = i.next();
    166             if (base.getName().equals(baseName)) {
    167                 register(i.previousIndex(), new EntryImpl(name, filter));
    168                 break;
    169             }
    170         }
    171     }
    172
    173     /**
    174      * @see IoFilterChain#addAfter(String, String, IoFilter)
    175      */
    176     public synchronized void addAfter(String baseName, String name,
    177             IoFilter filter) {
    178         checkBaseName(baseName);
    179
    180         for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
    181             Entry base = i.next();
    182             if (base.getName().equals(baseName)) {
    183                 register(i.nextIndex(), new EntryImpl(name, filter));
    184                 break;
    185             }
    186         }
    187     }
    188
    189     /**
    190      * @see IoFilterChain#remove(String)
    191      */
    192     public synchronized IoFilter remove(String name) {
    193         if (name == null) {
    194             throw new NullPointerException("name");
    195         }
    196
    197         for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
    198             Entry e = i.next();
    199             if (e.getName().equals(name)) {
    200                 entries.remove(i.previousIndex());
    201                 return e.getFilter();
    202             }
    203         }
    204
    205         throw new IllegalArgumentException("Unknown filter name: " + name);
    206     }
    207
    208     /**
    209      * @see IoFilterChain#clear()
    210      */
    211     public synchronized void clear() throws Exception {
    212         entries.clear();
    213     }
    214
    215     public void buildFilterChain(IoFilterChain chain) throws Exception {
    216         for (Iterator i = entries.iterator(); i.hasNext();) {
    217             Entry e = (Entry) i.next();
    218             chain.addLast(e.getName(), e.getFilter());
    219         }
    220     }
    221
    222     public String toString() {
    223         StringBuffer buf = new StringBuffer();
    224         buf.append("{ ");
    225
    226         boolean empty = true;
    227
    228         for (Iterator i = entries.iterator(); i.hasNext();) {
    229             Entry e = (Entry) i.next();
    230             if (!empty) {
    231                 buf.append(", ");
    232             } else {
    233                 empty = false;
    234             }
    235
    236             buf.append('(');
    237             buf.append(e.getName());
    238             buf.append(':');
    239             buf.append(e.getFilter());
    240             buf.append(')');
    241         }
    242
    243         if (empty) {
    244             buf.append("empty");
    245         }
    246
    247         buf.append(" }");
    248
    249         return buf.toString();
    250     }
    251
    252     public Object clone() {
    253         DefaultIoFilterChainBuilder ret = new DefaultIoFilterChainBuilder();
    254         for (Entry e : entries) {
    255             ret.addLast(e.getName(), e.getFilter());
    256         }
    257         return ret;
    258     }
    259
    260     private void checkBaseName(String baseName) {
    261         if (baseName == null) {
    262             throw new NullPointerException("baseName");
    263         }
    264
    265         if (!contains(baseName)) {
    266             throw new IllegalArgumentException("Unknown filter name: "
    267                     + baseName);
    268         }
    269     }
    270
    271     private void register(int index, Entry e) {
    272         if (contains(e.getName())) {
    273             throw new IllegalArgumentException(
    274                     "Other filter is using the same name: " + e.getName());
    275         }
    276
    277         entries.add(index, e);
    278     }
    279
    280     private static class EntryImpl implements Entry {
    281         private final String name;
    282
    283         private final IoFilter filter;
    284
    285         private EntryImpl(String name, IoFilter filter) {
    286             if (name == null) {
    287                 throw new NullPointerException("name");
    288             }
    289             if (filter == null) {
    290                 throw new NullPointerException("filter");
    291             }
    292
    293             this.name = name;
    294             this.filter = filter;
    295         }
    296
    297         public String getName() {
    298             return name;
    299         }
    300
    301         public IoFilter getFilter() {
    302             return filter;
    303         }
    304
    305         public NextFilter getNextFilter() {
    306             throw new IllegalStateException();
    307         }
    308
    309         public String toString() {
    310             return "(" + getName() + ':' + filter + ')';
    311         }
    312     }
    313 }