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