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 static final Logger LOGGER = LoggerFactory.getLogger(DefaultIoFilterChainBuilder.class);
65
66
67 private final List<Entry> entries;
68
69
70
71
72 public DefaultIoFilterChainBuilder() {
73 entries = new CopyOnWriteArrayList<>();
74 }
75
76
77
78
79
80
81 public DefaultIoFilterChainBuilder/../org/apache/mina/core/filterchain/DefaultIoFilterChainBuilder.html#DefaultIoFilterChainBuilder">DefaultIoFilterChainBuilder(DefaultIoFilterChainBuilder filterChain) {
82 if (filterChain == null) {
83 throw new IllegalArgumentException("filterChain");
84 }
85 entries = new CopyOnWriteArrayList<>(filterChain.entries);
86 }
87
88
89
90
91
92
93
94 public Entry getEntry(String name) {
95 for (Entry e : entries) {
96 if (e.getName().equals(name)) {
97 return e;
98 }
99 }
100
101 return null;
102 }
103
104
105
106
107
108
109
110 public Entry getEntry(IoFilter filter) {
111 for (Entry e : entries) {
112 if (e.getFilter() == filter) {
113 return e;
114 }
115 }
116
117 return null;
118 }
119
120
121
122
123
124
125
126 public Entry getEntry(Class<? extends IoFilter> filterType) {
127 for (Entry e : entries) {
128 if (filterType.isAssignableFrom(e.getFilter().getClass())) {
129 return e;
130 }
131 }
132
133 return null;
134 }
135
136
137
138
139
140
141
142 public IoFilter get(String name) {
143 Entry e = getEntry(name);
144
145 if (e == null) {
146 return null;
147 }
148
149 return e.getFilter();
150 }
151
152
153
154
155
156
157
158 public IoFilter get(Class<? extends IoFilter> filterType) {
159 Entry e = getEntry(filterType);
160
161 if (e == null) {
162 return null;
163 }
164
165 return e.getFilter();
166 }
167
168
169
170
171
172
173 public List<Entry> getAll() {
174 return new ArrayList<>(entries);
175 }
176
177
178
179
180
181
182 public List<Entry> getAllReversed() {
183 List<Entry> result = getAll();
184 Collections.reverse(result);
185
186 return result;
187 }
188
189
190
191
192
193
194
195 public boolean contains(String name) {
196 return getEntry(name) != null;
197 }
198
199
200
201
202
203
204
205 public boolean contains(IoFilter filter) {
206 return getEntry(filter) != null;
207 }
208
209
210
211
212
213
214
215 public boolean contains(Class<? extends IoFilter> filterType) {
216 return getEntry(filterType) != null;
217 }
218
219
220
221
222
223
224
225 public synchronized void addFirst(String name, IoFilter filter) {
226 register(0, new EntryImpl(name, filter));
227 }
228
229
230
231
232
233
234
235 public synchronized void addLast(String name, IoFilter filter) {
236 register(entries.size(), new EntryImpl(name, filter));
237 }
238
239
240
241
242
243
244
245
246 public synchronized void addBefore(String baseName, String name, IoFilter filter) {
247 checkBaseName(baseName);
248
249 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
250 Entry base = i.next();
251
252 if (base.getName().equals(baseName)) {
253 register(i.previousIndex(), new EntryImpl(name, filter));
254 break;
255 }
256 }
257 }
258
259
260
261
262
263
264
265
266 public synchronized void addAfter(String baseName, String name, IoFilter filter) {
267 checkBaseName(baseName);
268
269 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
270 Entry base = i.next();
271
272 if (base.getName().equals(baseName)) {
273 register(i.nextIndex(), new EntryImpl(name, filter));
274 break;
275 }
276 }
277 }
278
279
280
281
282
283
284
285 public synchronized IoFilter remove(String name) {
286 if (name == null) {
287 throw new IllegalArgumentException("name");
288 }
289
290 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
291 Entry e = i.next();
292
293 if (e.getName().equals(name)) {
294 entries.remove(i.previousIndex());
295
296 return e.getFilter();
297 }
298 }
299
300 throw new IllegalArgumentException("Unknown filter name: " + name);
301 }
302
303
304
305
306
307
308
309 public synchronized IoFilter"../../../../../org/apache/mina/core/filterchain/IoFilter.html#IoFilter">IoFilter remove(IoFilter filter) {
310 if (filter == null) {
311 throw new IllegalArgumentException("filter");
312 }
313
314 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
315 Entry e = i.next();
316
317 if (e.getFilter() == filter) {
318 entries.remove(i.previousIndex());
319
320 return e.getFilter();
321 }
322 }
323
324 throw new IllegalArgumentException("Filter not found: " + filter.getClass().getName());
325 }
326
327
328
329
330
331
332
333 public synchronized IoFilter remove(Class<? extends IoFilter> filterType) {
334 if (filterType == null) {
335 throw new IllegalArgumentException("filterType");
336 }
337
338 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
339 Entry e = i.next();
340
341 if (filterType.isAssignableFrom(e.getFilter().getClass())) {
342 entries.remove(i.previousIndex());
343
344 return e.getFilter();
345 }
346 }
347
348 throw new IllegalArgumentException("Filter not found: " + filterType.getName());
349 }
350
351
352
353
354
355
356
357
358 public synchronized IoFilter./org/apache/mina/core/filterchain/IoFilter.html#IoFilter">IoFilter replace(String name, IoFilter newFilter) {
359 checkBaseName(name);
360 EntryImpl e = (EntryImpl) getEntry(name);
361 IoFilter oldFilter = e.getFilter();
362 e.setFilter(newFilter);
363
364 return oldFilter;
365 }
366
367
368
369
370
371
372
373 public synchronized void replace(IoFilter../../../../org/apache/mina/core/filterchain/IoFilter.html#IoFilter">IoFilter oldFilter, IoFilter newFilter) {
374 for (Entry e : entries) {
375 if (e.getFilter() == oldFilter) {
376 ((EntryImpl) e).setFilter(newFilter);
377
378 return;
379 }
380 }
381
382 throw new IllegalArgumentException("Filter not found: " + oldFilter.getClass().getName());
383 }
384
385
386
387
388
389
390
391
392
393 public synchronized void replace(Class<? extends IoFilter> oldFilterType, IoFilter newFilter) {
394 for (Entry e : entries) {
395 if (oldFilterType.isAssignableFrom(e.getFilter().getClass())) {
396 ((EntryImpl) e).setFilter(newFilter);
397
398 return;
399 }
400 }
401
402 throw new IllegalArgumentException("Filter not found: " + oldFilterType.getName());
403 }
404
405
406
407
408 public synchronized void clear() {
409 entries.clear();
410 }
411
412
413
414
415
416
417
418
419
420
421 public void setFilters(Map<String, ? extends IoFilter> filters) {
422 if (filters == null) {
423 throw new IllegalArgumentException("filters");
424 }
425
426 if (!isOrderedMap(filters)) {
427 throw new IllegalArgumentException("filters is not an ordered map. Please try "
428 + LinkedHashMap.class.getName() + ".");
429 }
430
431 filters = new LinkedHashMap<>(filters);
432
433 for (Map.Entry<String, ? extends IoFilter> e : filters.entrySet()) {
434 if (e.getKey() == null) {
435 throw new IllegalArgumentException("filters contains a null key.");
436 }
437
438 if (e.getValue() == null) {
439 throw new IllegalArgumentException("filters contains a null value.");
440 }
441 }
442
443 synchronized (this) {
444 clear();
445
446 for (Map.Entry<String, ? extends IoFilter> e : filters.entrySet()) {
447 addLast(e.getKey(), e.getValue());
448 }
449 }
450 }
451
452 @SuppressWarnings("unchecked")
453 private boolean isOrderedMap(Map<String,? extends IoFilter> map) {
454 if (map == null) {
455 return false;
456 }
457
458 Class<?> mapType = map.getClass();
459
460 if (LinkedHashMap.class.isAssignableFrom(mapType)) {
461 if (LOGGER.isDebugEnabled()) {
462 LOGGER.debug("{} is an ordered map.", mapType.getSimpleName() );
463 }
464
465 return true;
466 }
467
468 if (LOGGER.isDebugEnabled()) {
469 LOGGER.debug("{} is not a {}", mapType.getName(), LinkedHashMap.class.getSimpleName());
470 }
471
472
473 Class<?> type = mapType;
474
475 while (type != null) {
476 for (Class<?> i : type.getInterfaces()) {
477 if (i.getName().endsWith("OrderedMap")) {
478 if (LOGGER.isDebugEnabled()) {
479 LOGGER.debug("{} is an ordered map (guessed from that it implements OrderedMap interface.)",
480 mapType.getSimpleName());
481 }
482
483 return true;
484 }
485 }
486
487 type = type.getSuperclass();
488 }
489
490 if (LOGGER.isDebugEnabled()) {
491 LOGGER.debug("{} doesn't implement OrderedMap interface.", mapType.getName() );
492 }
493
494
495
496 if (LOGGER.isDebugEnabled()) {
497 LOGGER.debug("Last resort; trying to create a new map instance with a "
498 + "default constructor and test if insertion order is maintained.");
499 }
500
501 Map<String,IoFilter> newMap;
502
503 try {
504 newMap = (Map<String,IoFilter>) mapType.newInstance();
505 } catch (Exception e) {
506 if (LOGGER.isDebugEnabled()) {
507 LOGGER.debug("Failed to create a new map instance of '{}'.", mapType.getName(), e);
508 }
509
510 return false;
511 }
512
513 Random rand = new Random();
514 List<String> expectedNames = new ArrayList<>();
515 IoFilter dummyFilter = new IoFilterAdapter();
516
517 for (int i = 0; i < 65536; i++) {
518 String filterName;
519
520 do {
521 filterName = String.valueOf(rand.nextInt());
522 } while (newMap.containsKey(filterName));
523
524 newMap.put(filterName, dummyFilter);
525 expectedNames.add(filterName);
526
527 Iterator<String> it = expectedNames.iterator();
528
529 for (Object key : newMap.keySet()) {
530 if (!it.next().equals(key)) {
531 if (LOGGER.isDebugEnabled()) {
532 LOGGER.debug("The specified map didn't pass the insertion order test after {} tries.", (i + 1));
533 }
534
535 return false;
536 }
537 }
538 }
539
540 if (LOGGER.isDebugEnabled()) {
541 LOGGER.debug("The specified map passed the insertion order test.");
542 }
543
544 return true;
545 }
546
547
548
549
550 @Override
551 public void buildFilterChain(IoFilterChain chain) throws Exception {
552 for (Entry e : entries) {
553 chain.addLast(e.getName(), e.getFilter());
554 }
555 }
556
557
558
559
560 @Override
561 public String toString() {
562 StringBuilder buf = new StringBuilder();
563 buf.append("{ ");
564
565 boolean empty = true;
566
567 for (Entry e : entries) {
568 if (!empty) {
569 buf.append(", ");
570 } else {
571 empty = false;
572 }
573
574 buf.append('(');
575 buf.append(e.getName());
576 buf.append(':');
577 buf.append(e.getFilter());
578 buf.append(')');
579 }
580
581 if (empty) {
582 buf.append("empty");
583 }
584
585 buf.append(" }");
586
587 return buf.toString();
588 }
589
590 private void checkBaseName(String baseName) {
591 if (baseName == null) {
592 throw new IllegalArgumentException("baseName");
593 }
594
595 if (!contains(baseName)) {
596 throw new IllegalArgumentException("Unknown filter name: " + baseName);
597 }
598 }
599
600 private void register(int index, Entry e) {
601 if (contains(e.getName())) {
602 throw new IllegalArgumentException("Other filter is using the same name: " + e.getName());
603 }
604
605 entries.add(index, e);
606 }
607
608 private final class EntryImpl implements Entry {
609 private final String name;
610
611 private volatile IoFilter filter;
612
613 private EntryImpl(String name, IoFilter filter) {
614 if (name == null) {
615 throw new IllegalArgumentException("name");
616 }
617
618 if (filter == null) {
619 throw new IllegalArgumentException("filter");
620 }
621
622 this.name = name;
623 this.filter = filter;
624 }
625
626
627
628
629 @Override
630 public String getName() {
631 return name;
632 }
633
634
635
636
637 @Override
638 public IoFilter getFilter() {
639 return filter;
640 }
641
642 private void setFilter(IoFilter filter) {
643 this.filter = filter;
644 }
645
646
647
648
649 @Override
650 public NextFilter getNextFilter() {
651 throw new IllegalStateException();
652 }
653
654 @Override
655 public String toString() {
656 return "(" + getName() + ':' + filter + ')';
657 }
658
659
660
661
662 @Override
663 public void addAfter(String name, IoFilter filter) {
664 DefaultIoFilterChainBuilder.this.addAfter(getName(), name, filter);
665 }
666
667
668
669
670 @Override
671 public void addBefore(String name, IoFilter filter) {
672 DefaultIoFilterChainBuilder.this.addBefore(getName(), name, filter);
673 }
674
675
676
677
678 @Override
679 public void remove() {
680 DefaultIoFilterChainBuilder.this.remove(getName());
681 }
682
683
684
685
686 @Override
687 public void replace(IoFilter newFilter) {
688 DefaultIoFilterChainBuilder.this.replace(getName(), newFilter);
689 }
690 }
691 }