1 20 package org.apache.mina.common.support; 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.common.ConnectFuture; 29 import org.apache.mina.common.IdleStatus; 30 import org.apache.mina.common.IoFilter; 31 import org.apache.mina.common.IoFilterAdapter; 32 import org.apache.mina.common.IoFilterChain; 33 import org.apache.mina.common.IoFilterLifeCycleException; 34 import org.apache.mina.common.IoSession; 35 import org.apache.mina.common.IoFilter.NextFilter; 36 import org.apache.mina.common.IoFilter.WriteRequest; 37 import org.apache.mina.util.ByteBufferUtil; 38 import org.apache.mina.util.SessionLog; 39 40 53 public abstract class AbstractIoFilterChain implements IoFilterChain { 54 60 public static final String CONNECT_FUTURE = AbstractIoFilterChain.class 61 .getName() 62 + ".connectFuture"; 63 64 private final IoSession session; 65 66 private final Map <String , Entry> name2entry = new HashMap <String , Entry>(); 67 68 private final EntryImpl head; 69 70 private final EntryImpl tail; 71 72 protected AbstractIoFilterChain(IoSession session) { 73 if (session == null) { 74 throw new NullPointerException ("session"); 75 } 76 77 this.session = session; 78 head = new EntryImpl(null, null, "head", new HeadFilter()); 79 tail = new EntryImpl(head, null, "tail", new TailFilter()); 80 head.nextEntry = tail; 81 } 82 83 public IoSession getSession() { 84 return session; 85 } 86 87 public Entry getEntry(String name) { 88 Entry e = name2entry.get(name); 89 if (e == null) { 90 return null; 91 } 92 return e; 93 } 94 95 public IoFilter get(String name) { 96 Entry e = getEntry(name); 97 if (e == null) { 98 return null; 99 } 100 101 return e.getFilter(); 102 } 103 104 public NextFilter getNextFilter(String name) { 105 Entry e = getEntry(name); 106 if (e == null) { 107 return null; 108 } 109 110 return e.getNextFilter(); 111 } 112 113 public synchronized void addFirst(String name, IoFilter filter) { 114 checkAddable(name); 115 register(head, name, filter); 116 } 117 118 public synchronized void addLast(String name, IoFilter filter) { 119 checkAddable(name); 120 register(tail.prevEntry, name, filter); 121 } 122 123 public synchronized void addBefore(String baseName, String name, 124 IoFilter filter) { 125 EntryImpl baseEntry = checkOldName(baseName); 126 checkAddable(name); 127 register(baseEntry.prevEntry, name, filter); 128 } 129 130 public synchronized void addAfter(String baseName, String name, 131 IoFilter filter) { 132 EntryImpl baseEntry = checkOldName(baseName); 133 checkAddable(name); 134 register(baseEntry, name, filter); 135 } 136 137 public synchronized IoFilter remove(String name) { 138 EntryImpl entry = checkOldName(name); 139 deregister(entry); 140 return entry.getFilter(); 141 } 142 143 public synchronized void clear() throws Exception { 144 Iterator <String > it = new ArrayList <String >(name2entry.keySet()) 145 .iterator(); 146 while (it.hasNext()) { 147 this.remove(it.next()); 148 } 149 } 150 151 private void register(EntryImpl prevEntry, String name, IoFilter filter) { 152 EntryImpl newEntry = new EntryImpl(prevEntry, prevEntry.nextEntry, 153 name, filter); 154 155 try { 156 filter.onPreAdd(this, name, newEntry.getNextFilter()); 157 } catch (Exception e) { 158 throw new IoFilterLifeCycleException("onPreAdd(): " + name + ':' 159 + filter + " in " + getSession(), e); 160 } 161 162 prevEntry.nextEntry.prevEntry = newEntry; 163 prevEntry.nextEntry = newEntry; 164 name2entry.put(name, newEntry); 165 166 try { 167 filter.onPostAdd(this, name, newEntry.getNextFilter()); 168 } catch (Exception e) { 169 deregister0(newEntry); 170 throw new IoFilterLifeCycleException("onPostAdd(): " + name + ':' 171 + filter + " in " + getSession(), e); 172 } 173 } 174 175 private void deregister(EntryImpl entry) { 176 IoFilter filter = entry.getFilter(); 177 178 try { 179 filter.onPreRemove(this, entry.getName(), entry.getNextFilter()); 180 } catch (Exception e) { 181 throw new IoFilterLifeCycleException("onPreRemove(): " 182 + entry.getName() + ':' + filter + " in " + getSession(), e); 183 } 184 185 deregister0(entry); 186 187 try { 188 filter.onPostRemove(this, entry.getName(), entry.getNextFilter()); 189 } catch (Exception e) { 190 throw new IoFilterLifeCycleException("onPostRemove(): " 191 + entry.getName() + ':' + filter + " in " + getSession(), e); 192 } 193 } 194 195 private void deregister0(EntryImpl entry) { 196 EntryImpl prevEntry = entry.prevEntry; 197 EntryImpl nextEntry = entry.nextEntry; 198 prevEntry.nextEntry = nextEntry; 199 nextEntry.prevEntry = prevEntry; 200 201 name2entry.remove(entry.name); 202 } 203 204 209 private EntryImpl checkOldName(String baseName) { 210 EntryImpl e = (EntryImpl) name2entry.get(baseName); 211 if (e == null) { 212 throw new IllegalArgumentException ("Unknown filter name:" 213 + baseName); 214 } 215 return e; 216 } 217 218 221 private void checkAddable(String name) { 222 if (name2entry.containsKey(name)) { 223 throw new IllegalArgumentException ( 224 "Other filter is using the same name '" + name + "'"); 225 } 226 } 227 228 public void fireSessionCreated(IoSession session) { 229 Entry head = this.head; 230 callNextSessionCreated(head, session); 231 } 232 233 private void callNextSessionCreated(Entry entry, IoSession session) { 234 try { 235 entry.getFilter().sessionCreated(entry.getNextFilter(), session); 236 } catch (Throwable e) { 237 fireExceptionCaught(session, e); 238 } 239 } 240 241 public void fireSessionOpened(IoSession session) { 242 Entry head = this.head; 243 callNextSessionOpened(head, session); 244 } 245 246 private void callNextSessionOpened(Entry entry, IoSession session) { 247 try { 248 entry.getFilter().sessionOpened(entry.getNextFilter(), session); 249 } catch (Throwable e) { 250 fireExceptionCaught(session, e); 251 } 252 } 253 254 public void fireSessionClosed(IoSession session) { 255 try { 257 session.getCloseFuture().setClosed(); 258 } catch (Throwable t) { 259 fireExceptionCaught(session, t); 260 } 261 262 Entry head = this.head; 264 callNextSessionClosed(head, session); 265 } 266 267 private void callNextSessionClosed(Entry entry, IoSession session) { 268 try { 269 entry.getFilter().sessionClosed(entry.getNextFilter(), session); 270 271 } catch (Throwable e) { 272 fireExceptionCaught(session, e); 273 } 274 } 275 276 public void fireSessionIdle(IoSession session, IdleStatus status) { 277 Entry head = this.head; 278 callNextSessionIdle(head, session, status); 279 } 280 281 private void callNextSessionIdle(Entry entry, IoSession session, 282 IdleStatus status) { 283 try { 284 entry.getFilter().sessionIdle(entry.getNextFilter(), session, 285 status); 286 } catch (Throwable e) { 287 fireExceptionCaught(session, e); 288 } 289 } 290 291 public void fireMessageReceived(IoSession session, Object message) { 292 Entry head = this.head; 293 callNextMessageReceived(head, session, message); 294 } 295 296 private void callNextMessageReceived(Entry entry, IoSession session, 297 Object message) { 298 try { 299 entry.getFilter().messageReceived(entry.getNextFilter(), session, 300 message); 301 } catch (Throwable e) { 302 fireExceptionCaught(session, e); 303 } 304 } 305 306 public void fireMessageSent(IoSession session, WriteRequest request) { 307 try { 308 request.getFuture().setWritten(true); 309 } catch (Throwable t) { 310 fireExceptionCaught(session, t); 311 } 312 313 Entry head = this.head; 314 callNextMessageSent(head, session, request.getMessage()); 315 } 316 317 private void callNextMessageSent(Entry entry, IoSession session, 318 Object message) { 319 try { 320 entry.getFilter().messageSent(entry.getNextFilter(), session, 321 message); 322 } catch (Throwable e) { 323 fireExceptionCaught(session, e); 324 } 325 } 326 327 public void fireExceptionCaught(IoSession session, Throwable cause) { 328 ConnectFuture future = (ConnectFuture) session 331 .removeAttribute(CONNECT_FUTURE); 332 if (future == null) { 333 Entry head = this.head; 334 callNextExceptionCaught(head, session, cause); 335 } else { 336 future.setException(cause); 339 } 340 } 341 342 private void callNextExceptionCaught(Entry entry, IoSession session, 343 Throwable cause) { 344 try { 345 entry.getFilter().exceptionCaught(entry.getNextFilter(), session, 346 cause); 347 } catch (Throwable e) { 348 SessionLog.warn(session, 349 "Unexpected exception from exceptionCaught handler.", e); 350 } 351 } 352 353 public void fireFilterWrite(IoSession session, WriteRequest writeRequest) { 354 Entry tail = this.tail; 355 callPreviousFilterWrite(tail, session, writeRequest); 356 } 357 358 private void callPreviousFilterWrite(Entry entry, IoSession session, 359 WriteRequest writeRequest) { 360 try { 361 entry.getFilter().filterWrite(entry.getNextFilter(), session, 362 writeRequest); 363 } catch (Throwable e) { 364 fireExceptionCaught(session, e); 365 } 366 } 367 368 public void fireFilterClose(IoSession session) { 369 Entry tail = this.tail; 370 callPreviousFilterClose(tail, session); 371 } 372 373 private void callPreviousFilterClose(Entry entry, IoSession session) { 374 try { 375 entry.getFilter().filterClose(entry.getNextFilter(), session); 376 } catch (Throwable e) { 377 fireExceptionCaught(session, e); 378 } 379 } 380 381 public List <Entry> getAll() { 382 List <Entry> list = new ArrayList <Entry>(); 383 EntryImpl e = head.nextEntry; 384 while (e != tail) { 385 list.add(e); 386 e = e.nextEntry; 387 } 388 389 return list; 390 } 391 392 public List <Entry> getAllReversed() { 393 List <Entry> list = new ArrayList <Entry>(); 394 EntryImpl e = tail.prevEntry; 395 while (e != head) { 396 list.add(e); 397 e = e.prevEntry; 398 } 399 return list; 400 } 401 402 public boolean contains(String name) { 403 return getEntry(name) != null; 404 } 405 406 public boolean contains(IoFilter filter) { 407 EntryImpl e = head.nextEntry; 408 while (e != tail) { 409 if (e.getFilter() == filter) { 410 return true; 411 } 412 e = e.nextEntry; 413 } 414 return false; 415 } 416 417 public boolean contains(Class <? extends IoFilter> filterType) { 418 EntryImpl e = head.nextEntry; 419 while (e != tail) { 420 if (filterType.isAssignableFrom(e.getFilter().getClass())) { 421 return true; 422 } 423 e = e.nextEntry; 424 } 425 return false; 426 } 427 428 public String toString() { 429 StringBuffer buf = new StringBuffer (); 430 buf.append("{ "); 431 432 boolean empty = true; 433 434 EntryImpl e = head.nextEntry; 435 while (e != tail) { 436 if (!empty) { 437 buf.append(", "); 438 } else { 439 empty = false; 440 } 441 442 buf.append('('); 443 buf.append(e.getName()); 444 buf.append(':'); 445 buf.append(e.getFilter()); 446 buf.append(')'); 447 448 e = e.nextEntry; 449 } 450 451 if (empty) { 452 buf.append("empty"); 453 } 454 455 buf.append(" }"); 456 457 return buf.toString(); 458 } 459 460 protected void finalize() throws Throwable { 461 try { 462 this.clear(); 463 } finally { 464 super.finalize(); 465 } 466 } 467 468 protected abstract void doWrite(IoSession session, WriteRequest writeRequest) 469 throws Exception ; 470 471 protected abstract void doClose(IoSession session) throws Exception ; 472 473 private class HeadFilter extends IoFilterAdapter { 474 public void sessionCreated(NextFilter nextFilter, IoSession session) { 475 nextFilter.sessionCreated(session); 476 } 477 478 public void sessionOpened(NextFilter nextFilter, IoSession session) { 479 nextFilter.sessionOpened(session); 480 } 481 482 public void sessionClosed(NextFilter nextFilter, IoSession session) { 483 nextFilter.sessionClosed(session); 484 } 485 486 public void sessionIdle(NextFilter nextFilter, IoSession session, 487 IdleStatus status) { 488 nextFilter.sessionIdle(session, status); 489 } 490 491 public void exceptionCaught(NextFilter nextFilter, IoSession session, 492 Throwable cause) { 493 nextFilter.exceptionCaught(session, cause); 494 } 495 496 public void messageReceived(NextFilter nextFilter, IoSession session, 497 Object message) { 498 nextFilter.messageReceived(session, message); 499 } 500 501 public void messageSent(NextFilter nextFilter, IoSession session, 502 Object message) { 503 nextFilter.messageSent(session, message); 504 } 505 506 public void filterWrite(NextFilter nextFilter, IoSession session, 507 WriteRequest writeRequest) throws Exception { 508 if (session.getTransportType().getEnvelopeType().isAssignableFrom( 509 writeRequest.getMessage().getClass())) { 510 doWrite(session, writeRequest); 511 } else { 512 throw new IllegalStateException ( 513 "Write requests must be transformed to " 514 + session.getTransportType().getEnvelopeType() 515 + ": " + writeRequest); 516 } 517 } 518 519 public void filterClose(NextFilter nextFilter, IoSession session) 520 throws Exception { 521 doClose(session); 522 } 523 } 524 525 private static class TailFilter extends IoFilterAdapter { 526 public void sessionCreated(NextFilter nextFilter, IoSession session) 527 throws Exception { 528 session.getHandler().sessionCreated(session); 529 } 530 531 public void sessionOpened(NextFilter nextFilter, IoSession session) 532 throws Exception { 533 try { 534 session.getHandler().sessionOpened(session); 535 } finally { 536 ConnectFuture future = (ConnectFuture) session 539 .removeAttribute(CONNECT_FUTURE); 540 if (future != null) { 541 future.setSession(session); 542 } 543 } 544 } 545 546 public void sessionClosed(NextFilter nextFilter, IoSession session) 547 throws Exception { 548 try { 549 session.getHandler().sessionClosed(session); 550 } finally { 551 session.getFilterChain().clear(); 553 } 554 } 555 556 public void sessionIdle(NextFilter nextFilter, IoSession session, 557 IdleStatus status) throws Exception { 558 session.getHandler().sessionIdle(session, status); 559 } 560 561 public void exceptionCaught(NextFilter nextFilter, IoSession session, 562 Throwable cause) throws Exception { 563 session.getHandler().exceptionCaught(session, cause); 564 } 565 566 public void messageReceived(NextFilter nextFilter, IoSession session, 567 Object message) throws Exception { 568 try { 569 session.getHandler().messageReceived(session, message); 570 } finally { 571 ByteBufferUtil.releaseIfPossible(message); 572 } 573 } 574 575 public void messageSent(NextFilter nextFilter, IoSession session, 576 Object message) throws Exception { 577 try { 578 session.getHandler().messageSent(session, message); 579 } finally { 580 ByteBufferUtil.releaseIfPossible(message); 581 } 582 } 583 584 public void filterWrite(NextFilter nextFilter, IoSession session, 585 WriteRequest writeRequest) throws Exception { 586 nextFilter.filterWrite(session, writeRequest); 587 } 588 589 public void filterClose(NextFilter nextFilter, IoSession session) 590 throws Exception { 591 nextFilter.filterClose(session); 592 } 593 } 594 595 private class EntryImpl implements Entry { 596 private EntryImpl prevEntry; 597 598 private EntryImpl nextEntry; 599 600 private final String name; 601 602 private final IoFilter filter; 603 604 private final NextFilter nextFilter; 605 606 private EntryImpl(EntryImpl prevEntry, EntryImpl nextEntry, 607 String name, IoFilter filter) { 608 if (filter == null) { 609 throw new NullPointerException ("filter"); 610 } 611 if (name == null) { 612 throw new NullPointerException ("name"); 613 } 614 615 this.prevEntry = prevEntry; 616 this.nextEntry = nextEntry; 617 this.name = name; 618 this.filter = filter; 619 this.nextFilter = new NextFilter() { 620 public void sessionCreated(IoSession session) { 621 Entry nextEntry = EntryImpl.this.nextEntry; 622 callNextSessionCreated(nextEntry, session); 623 } 624 625 public void sessionOpened(IoSession session) { 626 Entry nextEntry = EntryImpl.this.nextEntry; 627 callNextSessionOpened(nextEntry, session); 628 } 629 630 public void sessionClosed(IoSession session) { 631 Entry nextEntry = EntryImpl.this.nextEntry; 632 callNextSessionClosed(nextEntry, session); 633 } 634 635 public void sessionIdle(IoSession session, IdleStatus status) { 636 Entry nextEntry = EntryImpl.this.nextEntry; 637 callNextSessionIdle(nextEntry, session, status); 638 } 639 640 public void exceptionCaught(IoSession session, Throwable cause) { 641 Entry nextEntry = EntryImpl.this.nextEntry; 642 callNextExceptionCaught(nextEntry, session, cause); 643 } 644 645 public void messageReceived(IoSession session, Object message) { 646 Entry nextEntry = EntryImpl.this.nextEntry; 647 callNextMessageReceived(nextEntry, session, message); 648 } 649 650 public void messageSent(IoSession session, Object message) { 651 Entry nextEntry = EntryImpl.this.nextEntry; 652 callNextMessageSent(nextEntry, session, message); 653 } 654 655 public void filterWrite(IoSession session, 656 WriteRequest writeRequest) { 657 Entry nextEntry = EntryImpl.this.prevEntry; 658 callPreviousFilterWrite(nextEntry, session, writeRequest); 659 } 660 661 public void filterClose(IoSession session) { 662 Entry nextEntry = EntryImpl.this.prevEntry; 663 callPreviousFilterClose(nextEntry, session); 664 } 665 }; 666 } 667 668 public String getName() { 669 return name; 670 } 671 672 public IoFilter getFilter() { 673 return filter; 674 } 675 676 public NextFilter getNextFilter() { 677 return nextFilter; 678 } 679 680 public String toString() { 681 return "(" + getName() + ':' + filter + ')'; 682 } 683 } 684 } 685 | Popular Tags |