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