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