1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.handler.chain;
21
22 import java.util.ArrayList;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.concurrent.ConcurrentHashMap;
27
28 import org.apache.mina.core.session.IoSession;
29
30
31
32
33
34
35 public class IoHandlerChain implements IoHandlerCommand {
36 private static volatile int nextId = 0;
37
38 private final int id = nextId++;
39
40 private final String NEXT_COMMAND = IoHandlerChain.class.getName() + '.' + id + ".nextCommand";
41
42 private final Map<String, Entry> name2entry = new ConcurrentHashMap<String, Entry>();
43
44 private final Entry head;
45
46 private final Entry tail;
47
48
49
50
51 public IoHandlerChain() {
52 head = new Entry(null, null, "head", createHeadCommand());
53 tail = new Entry(head, null, "tail", createTailCommand());
54 head.nextEntry = tail;
55 }
56
57 private IoHandlerCommand createHeadCommand() {
58 return new IoHandlerCommand() {
59 public void execute(NextCommand next, IoSession session, Object message) throws Exception {
60 next.execute(session, message);
61 }
62 };
63 }
64
65 private IoHandlerCommand createTailCommand() {
66 return new IoHandlerCommand() {
67 public void execute(NextCommand next, IoSession session, Object message) throws Exception {
68 next = (NextCommand) session.getAttribute(NEXT_COMMAND);
69 if (next != null) {
70 next.execute(session, message);
71 }
72 }
73 };
74 }
75
76 public Entry getEntry(String name) {
77 Entry e = name2entry.get(name);
78 if (e == null) {
79 return null;
80 }
81 return e;
82 }
83
84 public IoHandlerCommand get(String name) {
85 Entry e = getEntry(name);
86 if (e == null) {
87 return null;
88 }
89
90 return e.getCommand();
91 }
92
93 public NextCommand getNextCommand(String name) {
94 Entry e = getEntry(name);
95 if (e == null) {
96 return null;
97 }
98
99 return e.getNextCommand();
100 }
101
102 public synchronized void addFirst(String name, IoHandlerCommand command) {
103 checkAddable(name);
104 register(head, name, command);
105 }
106
107 public synchronized void addLast(String name, IoHandlerCommand command) {
108 checkAddable(name);
109 register(tail.prevEntry, name, command);
110 }
111
112 public synchronized void addBefore(String baseName, String name, IoHandlerCommand command) {
113 Entry baseEntry = checkOldName(baseName);
114 checkAddable(name);
115 register(baseEntry.prevEntry, name, command);
116 }
117
118 public synchronized void addAfter(String baseName, String name, IoHandlerCommand command) {
119 Entry baseEntry = checkOldName(baseName);
120 checkAddable(name);
121 register(baseEntry, name, command);
122 }
123
124 public synchronized IoHandlerCommand remove(String name) {
125 Entry entry = checkOldName(name);
126 deregister(entry);
127 return entry.getCommand();
128 }
129
130 public synchronized void clear() throws Exception {
131 Iterator<String> it = new ArrayList<String>(name2entry.keySet()).iterator();
132 while (it.hasNext()) {
133 this.remove(it.next());
134 }
135 }
136
137 private void register(Entry prevEntry, String name, IoHandlerCommand command) {
138 Entry newEntry = new Entry(prevEntry, prevEntry.nextEntry, name, command);
139 prevEntry.nextEntry.prevEntry = newEntry;
140 prevEntry.nextEntry = newEntry;
141
142 name2entry.put(name, newEntry);
143 }
144
145 private void deregister(Entry entry) {
146 Entry prevEntry = entry.prevEntry;
147 Entry nextEntry = entry.nextEntry;
148 prevEntry.nextEntry = nextEntry;
149 nextEntry.prevEntry = prevEntry;
150
151 name2entry.remove(entry.name);
152 }
153
154
155
156
157
158
159 private Entry checkOldName(String baseName) {
160 Entry e = name2entry.get(baseName);
161 if (e == null) {
162 throw new IllegalArgumentException("Unknown filter name:" + baseName);
163 }
164 return e;
165 }
166
167
168
169
170 private void checkAddable(String name) {
171 if (name2entry.containsKey(name)) {
172 throw new IllegalArgumentException("Other filter is using the same name '" + name + "'");
173 }
174 }
175
176 public void execute(NextCommand next, IoSession session, Object message) throws Exception {
177 if (next != null) {
178 session.setAttribute(NEXT_COMMAND, next);
179 }
180
181 try {
182 callNextCommand(head, session, message);
183 } finally {
184 session.removeAttribute(NEXT_COMMAND);
185 }
186 }
187
188 private void callNextCommand(Entry entry, IoSession session, Object message) throws Exception {
189 entry.getCommand().execute(entry.getNextCommand(), session, message);
190 }
191
192 public List<Entry> getAll() {
193 List<Entry> list = new ArrayList<Entry>();
194 Entry e = head.nextEntry;
195 while (e != tail) {
196 list.add(e);
197 e = e.nextEntry;
198 }
199
200 return list;
201 }
202
203 public List<Entry> getAllReversed() {
204 List<Entry> list = new ArrayList<Entry>();
205 Entry e = tail.prevEntry;
206 while (e != head) {
207 list.add(e);
208 e = e.prevEntry;
209 }
210 return list;
211 }
212
213 public boolean contains(String name) {
214 return getEntry(name) != null;
215 }
216
217 public boolean contains(IoHandlerCommand command) {
218 Entry e = head.nextEntry;
219 while (e != tail) {
220 if (e.getCommand() == command) {
221 return true;
222 }
223 e = e.nextEntry;
224 }
225 return false;
226 }
227
228 public boolean contains(Class<? extends IoHandlerCommand> commandType) {
229 Entry e = head.nextEntry;
230 while (e != tail) {
231 if (commandType.isAssignableFrom(e.getCommand().getClass())) {
232 return true;
233 }
234 e = e.nextEntry;
235 }
236 return false;
237 }
238
239 @Override
240 public String toString() {
241 StringBuilder buf = new StringBuilder();
242 buf.append("{ ");
243
244 boolean empty = true;
245
246 Entry e = head.nextEntry;
247 while (e != tail) {
248 if (!empty) {
249 buf.append(", ");
250 } else {
251 empty = false;
252 }
253
254 buf.append('(');
255 buf.append(e.getName());
256 buf.append(':');
257 buf.append(e.getCommand());
258 buf.append(')');
259
260 e = e.nextEntry;
261 }
262
263 if (empty) {
264 buf.append("empty");
265 }
266
267 buf.append(" }");
268
269 return buf.toString();
270 }
271
272
273
274
275
276
277 public class Entry {
278 private Entry prevEntry;
279
280 private Entry nextEntry;
281
282 private final String name;
283
284 private final IoHandlerCommand command;
285
286 private final NextCommand nextCommand;
287
288 private Entry(Entry prevEntry, Entry nextEntry, String name, IoHandlerCommand command) {
289 if (command == null) {
290 throw new IllegalArgumentException("command");
291 }
292 if (name == null) {
293 throw new IllegalArgumentException("name");
294 }
295
296 this.prevEntry = prevEntry;
297 this.nextEntry = nextEntry;
298 this.name = name;
299 this.command = command;
300 this.nextCommand = new NextCommand() {
301 public void execute(IoSession session, Object message) throws Exception {
302 Entry nextEntry = Entry.this.nextEntry;
303 callNextCommand(nextEntry, session, message);
304 }
305 };
306 }
307
308
309
310
311 public String getName() {
312 return name;
313 }
314
315
316
317
318 public IoHandlerCommand getCommand() {
319 return command;
320 }
321
322
323
324
325 public NextCommand getNextCommand() {
326 return nextCommand;
327 }
328 }
329 }