1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.core.filterchain;
21
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.LinkedHashMap;
26 import java.util.List;
27 import java.util.ListIterator;
28 import java.util.Map;
29 import java.util.Random;
30 import java.util.concurrent.CopyOnWriteArrayList;
31
32 import org.apache.mina.core.filterchain.IoFilter.NextFilter;
33 import org.apache.mina.core.filterchain.IoFilterChain.Entry;
34 import org.apache.mina.core.session.IoSession;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public class DefaultIoFilterChainBuilder implements IoFilterChainBuilder {
63
64 private final Logger logger = LoggerFactory.getLogger(getClass());
65 private final List<Entry> entries;
66
67
68
69
70 public DefaultIoFilterChainBuilder() {
71 entries = new CopyOnWriteArrayList<Entry>();
72 }
73
74
75
76
77 public DefaultIoFilterChainBuilder(DefaultIoFilterChainBuilder filterChain) {
78 if (filterChain == null) {
79 throw new NullPointerException("filterChain");
80 }
81 entries = new CopyOnWriteArrayList<Entry>(filterChain.entries);
82 }
83
84
85
86
87 public Entry getEntry(String name) {
88 for (Entry e: entries) {
89 if (e.getName().equals(name)) {
90 return e;
91 }
92 }
93
94 return null;
95 }
96
97
98
99
100 public Entry getEntry(IoFilter filter) {
101 for (Entry e: entries) {
102 if (e.getFilter() == filter) {
103 return e;
104 }
105 }
106
107 return null;
108 }
109
110
111
112
113 public Entry getEntry(Class<? extends IoFilter> filterType) {
114 for (Entry e: entries) {
115 if (filterType.isAssignableFrom(e.getFilter().getClass())) {
116 return e;
117 }
118 }
119
120 return null;
121 }
122
123
124
125
126 public IoFilter get(String name) {
127 Entry e = getEntry(name);
128 if (e == null) {
129 return null;
130 }
131
132 return e.getFilter();
133 }
134
135
136
137
138 public IoFilter get(Class<? extends IoFilter> filterType) {
139 Entry e = getEntry(filterType);
140 if (e == null) {
141 return null;
142 }
143
144 return e.getFilter();
145 }
146
147
148
149
150 public List<Entry> getAll() {
151 return new ArrayList<Entry>(entries);
152 }
153
154
155
156
157 public List<Entry> getAllReversed() {
158 List<Entry> result = getAll();
159 Collections.reverse(result);
160 return result;
161 }
162
163
164
165
166 public boolean contains(String name) {
167 return getEntry(name) != null;
168 }
169
170
171
172
173 public boolean contains(IoFilter filter) {
174 return getEntry(filter) != null;
175 }
176
177
178
179
180 public boolean contains(Class<? extends IoFilter> filterType) {
181 return getEntry(filterType) != null;
182 }
183
184
185
186
187 public synchronized void addFirst(String name, IoFilter filter) {
188 register(0, new EntryImpl(name, filter));
189 }
190
191
192
193
194 public synchronized void addLast(String name, IoFilter filter) {
195 register(entries.size(), new EntryImpl(name, filter));
196 }
197
198
199
200
201 public synchronized void addBefore(String baseName, String name,
202 IoFilter filter) {
203 checkBaseName(baseName);
204
205 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
206 Entry base = i.next();
207 if (base.getName().equals(baseName)) {
208 register(i.previousIndex(), new EntryImpl(name, filter));
209 break;
210 }
211 }
212 }
213
214
215
216
217 public synchronized void addAfter(String baseName, String name,
218 IoFilter filter) {
219 checkBaseName(baseName);
220
221 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
222 Entry base = i.next();
223 if (base.getName().equals(baseName)) {
224 register(i.nextIndex(), new EntryImpl(name, filter));
225 break;
226 }
227 }
228 }
229
230
231
232
233 public synchronized IoFilter remove(String name) {
234 if (name == null) {
235 throw new NullPointerException("name");
236 }
237
238 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
239 Entry e = i.next();
240 if (e.getName().equals(name)) {
241 entries.remove(i.previousIndex());
242 return e.getFilter();
243 }
244 }
245
246 throw new IllegalArgumentException("Unknown filter name: " + name);
247 }
248
249
250
251
252 public synchronized IoFilter remove(IoFilter filter) {
253 if (filter == null) {
254 throw new NullPointerException("filter");
255 }
256
257 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
258 Entry e = i.next();
259 if (e.getFilter() == filter) {
260 entries.remove(i.previousIndex());
261 return e.getFilter();
262 }
263 }
264
265 throw new IllegalArgumentException("Filter not found: " + filter.getClass().getName());
266 }
267
268
269
270
271 public synchronized IoFilter remove(Class<? extends IoFilter> filterType) {
272 if (filterType == null) {
273 throw new NullPointerException("filterType");
274 }
275
276 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
277 Entry e = i.next();
278 if (filterType.isAssignableFrom(e.getFilter().getClass())) {
279 entries.remove(i.previousIndex());
280 return e.getFilter();
281 }
282 }
283
284 throw new IllegalArgumentException("Filter not found: " + filterType.getName());
285 }
286
287 public synchronized IoFilter replace(String name, IoFilter newFilter) {
288 checkBaseName(name);
289 EntryImpl e = (EntryImpl) get(name);
290 IoFilter oldFilter = e.getFilter();
291 e.setFilter(newFilter);
292 return oldFilter;
293 }
294
295 public synchronized void replace(IoFilter oldFilter, IoFilter newFilter) {
296 for (Entry e : entries) {
297 if (e.getFilter() == oldFilter) {
298 ((EntryImpl) e).setFilter(newFilter);
299 return;
300 }
301 }
302 throw new IllegalArgumentException("Filter not found: "
303 + oldFilter.getClass().getName());
304 }
305
306 public synchronized void replace(Class<? extends IoFilter> oldFilterType,
307 IoFilter newFilter) {
308 for (Entry e : entries) {
309 if (oldFilterType.isAssignableFrom(e.getFilter().getClass())) {
310 ((EntryImpl) e).setFilter(newFilter);
311 return;
312 }
313 }
314 throw new IllegalArgumentException("Filter not found: "
315 + oldFilterType.getName());
316 }
317
318
319
320
321 public synchronized void clear() {
322 entries.clear();
323 }
324
325
326
327
328
329
330
331
332 public void setFilters(Map<String, ? extends IoFilter> filters) {
333 if (filters == null) {
334 throw new NullPointerException("filters");
335 }
336
337 if (!isOrderedMap(filters)) {
338 throw new IllegalArgumentException(
339 "filters is not an ordered map. Please try " +
340 LinkedHashMap.class.getName() + ".");
341 }
342
343 filters = new LinkedHashMap<String, IoFilter>(filters);
344 for (Map.Entry<String, ? extends IoFilter> e: filters.entrySet()) {
345 if (e.getKey() == null) {
346 throw new NullPointerException("filters contains a null key.");
347 }
348 if (e.getValue() == null) {
349 throw new NullPointerException("filters contains a null value.");
350 }
351 }
352
353 synchronized (this) {
354 clear();
355 for (Map.Entry<String, ? extends IoFilter> e: filters.entrySet()) {
356 addLast(e.getKey(), e.getValue());
357 }
358 }
359 }
360
361 @SuppressWarnings("unchecked")
362 private boolean isOrderedMap(Map map) {
363 Class<?> mapType = map.getClass();
364 if (LinkedHashMap.class.isAssignableFrom(mapType)) {
365 if (logger.isDebugEnabled()) {
366 logger.debug(mapType.getSimpleName() + " is an ordered map.");
367 }
368 return true;
369 }
370
371 if (logger.isDebugEnabled()) {
372 logger.debug(mapType.getName() + " is not a " + LinkedHashMap.class.getSimpleName());
373 }
374
375
376 Class<?> type = mapType;
377 while (type != null) {
378 for (Class<?> i: type.getInterfaces()) {
379 if (i.getName().endsWith("OrderedMap")) {
380 if (logger.isDebugEnabled()) {
381 logger.debug(
382 mapType.getSimpleName() +
383 " is an ordered map (guessed from that it " +
384 " implements OrderedMap interface.)");
385 }
386 return true;
387 }
388 }
389 type = type.getSuperclass();
390 }
391
392 if (logger.isDebugEnabled()) {
393 logger.debug(
394 mapType.getName() +
395 " doesn't implement OrderedMap interface.");
396 }
397
398
399
400 logger.debug(
401 "Last resort; trying to create a new map instance with a " +
402 "default constructor and test if insertion order is " +
403 "maintained.");
404
405 Map newMap;
406 try {
407 newMap = (Map) mapType.newInstance();
408 } catch (Exception e) {
409 if (logger.isDebugEnabled()) {
410 logger.debug(
411 "Failed to create a new map instance of '" +
412 mapType.getName() +"'.", e);
413 }
414 return false;
415 }
416
417 Random rand = new Random();
418 List<String> expectedNames = new ArrayList<String>();
419 IoFilter dummyFilter = new IoFilterAdapter();
420 for (int i = 0; i < 65536; i ++) {
421 String filterName;
422 do {
423 filterName = String.valueOf(rand.nextInt());
424 } while (newMap.containsKey(filterName));
425
426 newMap.put(filterName, dummyFilter);
427 expectedNames.add(filterName);
428
429 Iterator<String> it = expectedNames.iterator();
430 for (Object key: newMap.keySet()) {
431 if (!it.next().equals(key)) {
432 if (logger.isDebugEnabled()) {
433 logger.debug(
434 "The specified map didn't pass the insertion " +
435 "order test after " + (i + 1) + " tries.");
436 }
437 return false;
438 }
439 }
440 }
441
442 if (logger.isDebugEnabled()) {
443 logger.debug(
444 "The specified map passed the insertion order test.");
445 }
446 return true;
447 }
448
449 public void buildFilterChain(IoFilterChain chain) throws Exception {
450 for (Entry e : entries) {
451 chain.addLast(e.getName(), e.getFilter());
452 }
453 }
454
455 @Override
456 public String toString() {
457 StringBuffer buf = new StringBuffer();
458 buf.append("{ ");
459
460 boolean empty = true;
461
462 for (Entry e : entries) {
463 if (!empty) {
464 buf.append(", ");
465 } else {
466 empty = false;
467 }
468
469 buf.append('(');
470 buf.append(e.getName());
471 buf.append(':');
472 buf.append(e.getFilter());
473 buf.append(')');
474 }
475
476 if (empty) {
477 buf.append("empty");
478 }
479
480 buf.append(" }");
481
482 return buf.toString();
483 }
484
485 private void checkBaseName(String baseName) {
486 if (baseName == null) {
487 throw new NullPointerException("baseName");
488 }
489
490 if (!contains(baseName)) {
491 throw new IllegalArgumentException("Unknown filter name: "
492 + baseName);
493 }
494 }
495
496 private void register(int index, Entry e) {
497 if (contains(e.getName())) {
498 throw new IllegalArgumentException(
499 "Other filter is using the same name: " + e.getName());
500 }
501
502 entries.add(index, e);
503 }
504
505 private class EntryImpl implements Entry {
506 private final String name;
507 private volatile IoFilter filter;
508
509 private EntryImpl(String name, IoFilter filter) {
510 if (name == null) {
511 throw new NullPointerException("name");
512 }
513 if (filter == null) {
514 throw new NullPointerException("filter");
515 }
516
517 this.name = name;
518 this.filter = filter;
519 }
520
521 public String getName() {
522 return name;
523 }
524
525 public IoFilter getFilter() {
526 return filter;
527 }
528
529 private void setFilter(IoFilter filter) {
530 this.filter = filter;
531 }
532
533 public NextFilter getNextFilter() {
534 throw new IllegalStateException();
535 }
536
537 @Override
538 public String toString() {
539 return "(" + getName() + ':' + filter + ')';
540 }
541
542 public void addAfter(String name, IoFilter filter) {
543 DefaultIoFilterChainBuilder.this.addAfter(getName(), name, filter);
544 }
545
546 public void addBefore(String name, IoFilter filter) {
547 DefaultIoFilterChainBuilder.this.addBefore(getName(), name, filter);
548 }
549
550 public void remove() {
551 DefaultIoFilterChainBuilder.this.remove(getName());
552 }
553
554 public void replace(IoFilter newFilter) {
555 DefaultIoFilterChainBuilder.this.replace(getName(), newFilter);
556 }
557 }
558 }