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