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  
28  import org.apache.mina.common.IoFilter.NextFilter;
29  import org.apache.mina.common.IoFilterChain.Entry;
30  
31  import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
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: 562335 $, $Date: 2007-08-03 07:28:02 +0200 (Fri, 03 Aug 2007) $
56   */
57  public class DefaultIoFilterChainBuilder implements IoFilterChainBuilder,
58          Cloneable {
59      private final List entries;
60  
61      /**
62       * Creates a new instance with an empty filter list.
63       */
64      public DefaultIoFilterChainBuilder() {
65          entries = new CopyOnWriteArrayList();
66      }
67  
68      /**
69       * @see IoFilterChain#getEntry(String)
70       */
71      public Entry getEntry(String name) {
72          for (Iterator i = entries.iterator(); i.hasNext(); ) {
73              Entry e = (Entry) i.next();
74              if (e.getName().equals(name)) {
75                  return e;
76              }
77          }
78          
79          return null;
80      }
81  
82      /**
83       * @see IoFilterChain#get(String)
84       */
85      public 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         for (ListIterator i = entries.listIterator(); i.hasNext();) {
183             Entry base = (Entry) i.next();
184             if (base.getName().equals(baseName)) {
185                 register(i.nextIndex(), new EntryImpl(name, filter));
186                 break;
187             }
188         }
189     }
190 
191     /**
192      * @see IoFilterChain#remove(String)
193      */
194     public synchronized IoFilter remove(String name) {
195         if (name == null) {
196             throw new NullPointerException("name");
197         }
198 
199         for (ListIterator i = entries.listIterator(); i.hasNext();) {
200             Entry e = (Entry) i.next();
201             if (e.getName().equals(name)) {
202                 entries.remove(i.previousIndex());
203                 return e.getFilter();
204             }
205         }
206 
207         throw new IllegalArgumentException("Unknown filter name: " + name);
208     }
209 
210     /**
211      * @see IoFilterChain#clear()
212      */
213     public synchronized void clear() throws Exception {
214         entries.clear();
215     }
216 
217     public void buildFilterChain(IoFilterChain chain) throws Exception {
218         for (Iterator i = entries.iterator(); i.hasNext();) {
219             Entry e = (Entry) i.next();
220             chain.addLast(e.getName(), e.getFilter());
221         }
222     }
223 
224     public String toString() {
225         StringBuffer buf = new StringBuffer();
226         buf.append("{ ");
227 
228         boolean empty = true;
229 
230         for (Iterator i = entries.iterator(); i.hasNext();) {
231             Entry e = (Entry) i.next();
232             if (!empty) {
233                 buf.append(", ");
234             } else {
235                 empty = false;
236             }
237 
238             buf.append('(');
239             buf.append(e.getName());
240             buf.append(':');
241             buf.append(e.getFilter());
242             buf.append(')');
243         }
244 
245         if (empty) {
246             buf.append("empty");
247         }
248 
249         buf.append(" }");
250 
251         return buf.toString();
252     }
253 
254     public Object clone() {
255         DefaultIoFilterChainBuilder ret = new DefaultIoFilterChainBuilder();
256         for (Iterator i = entries.iterator(); i.hasNext();) {
257             Entry e = (Entry) i.next();
258             ret.addLast(e.getName(), e.getFilter());
259         }
260         return ret;
261     }
262 
263     private void checkBaseName(String baseName) {
264         if (baseName == null) {
265             throw new NullPointerException("baseName");
266         }
267         
268         if (!contains(baseName)) {
269             throw new IllegalArgumentException("Unknown filter name: "
270                     + baseName);
271         }
272     }
273 
274     private void register(int index, Entry e) {
275         if (contains(e.getName())) {
276             throw new IllegalArgumentException(
277                     "Other filter is using the same name: " + e.getName());
278         }
279 
280         entries.add(index, e);
281     }
282 
283     private static class EntryImpl implements Entry {
284         private final String name;
285 
286         private final IoFilter filter;
287 
288         private EntryImpl(String name, IoFilter filter) {
289             if (name == null) {
290                 throw new NullPointerException("name");
291             }
292             if (filter == null) {
293                 throw new NullPointerException("filter");
294             }
295 
296             this.name = name;
297             this.filter = filter;
298         }
299 
300         public String getName() {
301             return name;
302         }
303 
304         public IoFilter getFilter() {
305             return filter;
306         }
307 
308         public NextFilter getNextFilter() {
309             throw new IllegalStateException();
310         }
311 
312         public String toString() {
313             return "(" + getName() + ':' + filter + ')';
314         }
315     }
316 }