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 =
65 LoggerFactory.getLogger(DefaultIoFilterChainBuilder.class);
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 NullPointerException("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,
203 IoFilter filter) {
204 checkBaseName(baseName);
205
206 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
207 Entry base = i.next();
208 if (base.getName().equals(baseName)) {
209 register(i.previousIndex(), new EntryImpl(name, filter));
210 break;
211 }
212 }
213 }
214
215
216
217
218 public synchronized void addAfter(String baseName, String name,
219 IoFilter filter) {
220 checkBaseName(baseName);
221
222 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
223 Entry base = i.next();
224 if (base.getName().equals(baseName)) {
225 register(i.nextIndex(), new EntryImpl(name, filter));
226 break;
227 }
228 }
229 }
230
231
232
233
234 public synchronized IoFilter remove(String name) {
235 if (name == null) {
236 throw new NullPointerException("name");
237 }
238
239 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
240 Entry e = i.next();
241 if (e.getName().equals(name)) {
242 entries.remove(i.previousIndex());
243 return e.getFilter();
244 }
245 }
246
247 throw new IllegalArgumentException("Unknown filter name: " + name);
248 }
249
250
251
252
253 public synchronized IoFilter remove(IoFilter filter) {
254 if (filter == null) {
255 throw new NullPointerException("filter");
256 }
257
258 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
259 Entry e = i.next();
260 if (e.getFilter() == filter) {
261 entries.remove(i.previousIndex());
262 return e.getFilter();
263 }
264 }
265
266 throw new IllegalArgumentException("Filter not found: " + filter.getClass().getName());
267 }
268
269
270
271
272 public synchronized IoFilter remove(Class<? extends IoFilter> filterType) {
273 if (filterType == null) {
274 throw new NullPointerException("filterType");
275 }
276
277 for (ListIterator<Entry> i = entries.listIterator(); i.hasNext();) {
278 Entry e = i.next();
279 if (filterType.isAssignableFrom(e.getFilter().getClass())) {
280 entries.remove(i.previousIndex());
281 return e.getFilter();
282 }
283 }
284
285 throw new IllegalArgumentException("Filter not found: " + filterType.getName());
286 }
287
288 public synchronized IoFilter replace(String name, IoFilter newFilter) {
289 checkBaseName(name);
290 EntryImpl e = (EntryImpl)getEntry(name);
291 IoFilter oldFilter = e.getFilter();
292 e.setFilter(newFilter);
293 return oldFilter;
294 }
295
296 public synchronized void replace(IoFilter oldFilter, IoFilter newFilter) {
297 for (Entry e : entries) {
298 if (e.getFilter() == oldFilter) {
299 ((EntryImpl) e).setFilter(newFilter);
300 return;
301 }
302 }
303 throw new IllegalArgumentException("Filter not found: "
304 + oldFilter.getClass().getName());
305 }
306
307 public synchronized void replace(Class<? extends IoFilter> oldFilterType,
308 IoFilter newFilter) {
309 for (Entry e : entries) {
310 if (oldFilterType.isAssignableFrom(e.getFilter().getClass())) {
311 ((EntryImpl) e).setFilter(newFilter);
312 return;
313 }
314 }
315 throw new IllegalArgumentException("Filter not found: "
316 + oldFilterType.getName());
317 }
318
319
320
321
322 public synchronized void clear() {
323 entries.clear();
324 }
325
326
327
328
329
330
331
332
333 public void setFilters(Map<String, ? extends IoFilter> filters) {
334 if (filters == null) {
335 throw new NullPointerException("filters");
336 }
337
338 if (!isOrderedMap(filters)) {
339 throw new IllegalArgumentException(
340 "filters is not an ordered map. Please try " +
341 LinkedHashMap.class.getName() + ".");
342 }
343
344 filters = new LinkedHashMap<String, IoFilter>(filters);
345 for (Map.Entry<String, ? extends IoFilter> e: filters.entrySet()) {
346 if (e.getKey() == null) {
347 throw new NullPointerException("filters contains a null key.");
348 }
349 if (e.getValue() == null) {
350 throw new NullPointerException("filters contains a null value.");
351 }
352 }
353
354 synchronized (this) {
355 clear();
356 for (Map.Entry<String, ? extends IoFilter> e: filters.entrySet()) {
357 addLast(e.getKey(), e.getValue());
358 }
359 }
360 }
361
362 @SuppressWarnings("unchecked")
363 private boolean isOrderedMap(Map map) {
364 Class<?> mapType = map.getClass();
365 if (LinkedHashMap.class.isAssignableFrom(mapType)) {
366 if (LOGGER.isDebugEnabled()) {
367 LOGGER.debug(mapType.getSimpleName() + " is an ordered map.");
368 }
369 return true;
370 }
371
372 if (LOGGER.isDebugEnabled()) {
373 LOGGER.debug(mapType.getName() + " is not a " + LinkedHashMap.class.getSimpleName());
374 }
375
376
377 Class<?> type = mapType;
378 while (type != null) {
379 for (Class<?> i: type.getInterfaces()) {
380 if (i.getName().endsWith("OrderedMap")) {
381 if (LOGGER.isDebugEnabled()) {
382 LOGGER.debug(
383 mapType.getSimpleName() +
384 " is an ordered map (guessed from that it " +
385 " implements OrderedMap interface.)");
386 }
387 return true;
388 }
389 }
390 type = type.getSuperclass();
391 }
392
393 if (LOGGER.isDebugEnabled()) {
394 LOGGER.debug(
395 mapType.getName() +
396 " doesn't implement OrderedMap interface.");
397 }
398
399
400
401 LOGGER.debug(
402 "Last resort; trying to create a new map instance with a " +
403 "default constructor and test if insertion order is " +
404 "maintained.");
405
406 Map newMap;
407 try {
408 newMap = (Map) mapType.newInstance();
409 } catch (Exception e) {
410 if (LOGGER.isDebugEnabled()) {
411 LOGGER.debug(
412 "Failed to create a new map instance of '" +
413 mapType.getName() +"'.", e);
414 }
415 return false;
416 }
417
418 Random rand = new Random();
419 List<String> expectedNames = new ArrayList<String>();
420 IoFilter dummyFilter = new IoFilterAdapter();
421 for (int i = 0; i < 65536; i ++) {
422 String filterName;
423 do {
424 filterName = String.valueOf(rand.nextInt());
425 } while (newMap.containsKey(filterName));
426
427 newMap.put(filterName, dummyFilter);
428 expectedNames.add(filterName);
429
430 Iterator<String> it = expectedNames.iterator();
431 for (Object key: newMap.keySet()) {
432 if (!it.next().equals(key)) {
433 if (LOGGER.isDebugEnabled()) {
434 LOGGER.debug(
435 "The specified map didn't pass the insertion " +
436 "order test after " + (i + 1) + " tries.");
437 }
438 return false;
439 }
440 }
441 }
442
443 if (LOGGER.isDebugEnabled()) {
444 LOGGER.debug(
445 "The specified map passed the insertion order test.");
446 }
447 return true;
448 }
449
450 public void buildFilterChain(IoFilterChain chain) throws Exception {
451 for (Entry e : entries) {
452 chain.addLast(e.getName(), e.getFilter());
453 }
454 }
455
456 @Override
457 public String toString() {
458 StringBuilder buf = new StringBuilder();
459 buf.append("{ ");
460
461 boolean empty = true;
462
463 for (Entry e : entries) {
464 if (!empty) {
465 buf.append(", ");
466 } else {
467 empty = false;
468 }
469
470 buf.append('(');
471 buf.append(e.getName());
472 buf.append(':');
473 buf.append(e.getFilter());
474 buf.append(')');
475 }
476
477 if (empty) {
478 buf.append("empty");
479 }
480
481 buf.append(" }");
482
483 return buf.toString();
484 }
485
486 private void checkBaseName(String baseName) {
487 if (baseName == null) {
488 throw new NullPointerException("baseName");
489 }
490
491 if (!contains(baseName)) {
492 throw new IllegalArgumentException("Unknown filter name: "
493 + baseName);
494 }
495 }
496
497 private void register(int index, Entry e) {
498 if (contains(e.getName())) {
499 throw new IllegalArgumentException(
500 "Other filter is using the same name: " + e.getName());
501 }
502
503 entries.add(index, e);
504 }
505
506 private class EntryImpl implements Entry {
507 private final String name;
508 private volatile IoFilter filter;
509
510 private EntryImpl(String name, IoFilter filter) {
511 if (name == null) {
512 throw new NullPointerException("name");
513 }
514 if (filter == null) {
515 throw new NullPointerException("filter");
516 }
517
518 this.name = name;
519 this.filter = filter;
520 }
521
522 public String getName() {
523 return name;
524 }
525
526 public IoFilter getFilter() {
527 return filter;
528 }
529
530 private void setFilter(IoFilter filter) {
531 this.filter = filter;
532 }
533
534 public NextFilter getNextFilter() {
535 throw new IllegalStateException();
536 }
537
538 @Override
539 public String toString() {
540 return "(" + getName() + ':' + filter + ')';
541 }
542
543 public void addAfter(String name, IoFilter filter) {
544 DefaultIoFilterChainBuilder.this.addAfter(getName(), name, filter);
545 }
546
547 public void addBefore(String name, IoFilter filter) {
548 DefaultIoFilterChainBuilder.this.addBefore(getName(), name, filter);
549 }
550
551 public void remove() {
552 DefaultIoFilterChainBuilder.this.remove(getName());
553 }
554
555 public void replace(IoFilter newFilter) {
556 DefaultIoFilterChainBuilder.this.replace(getName(), newFilter);
557 }
558 }
559 }