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