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