查看本类的 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.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 }