1 16 package org.mortbay.jetty.servlet; 17 18 import java.io.IOException ; 19 import java.util.ArrayList ; 20 import java.util.EventListener ; 21 import java.util.HashMap ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.Map ; 25 26 import javax.servlet.Filter ; 27 import javax.servlet.FilterChain ; 28 import javax.servlet.ServletContextAttributeEvent ; 29 import javax.servlet.ServletContextAttributeListener ; 30 import javax.servlet.ServletException ; 31 import javax.servlet.ServletRequest ; 32 import javax.servlet.ServletRequestAttributeListener ; 33 import javax.servlet.ServletRequestListener ; 34 import javax.servlet.ServletResponse ; 35 import javax.servlet.UnavailableException ; 36 import javax.servlet.http.HttpServletRequest ; 37 import javax.servlet.http.HttpServletResponse ; 38 import javax.servlet.http.HttpSessionActivationListener ; 39 import javax.servlet.http.HttpSessionAttributeListener ; 40 import javax.servlet.http.HttpSessionBindingListener ; 41 import javax.servlet.http.HttpSessionListener ; 42 43 import org.apache.commons.logging.Log; 44 import org.mortbay.log.LogFactory; 45 import org.mortbay.http.HttpContext; 46 import org.mortbay.http.HttpResponse; 47 import org.mortbay.http.PathMap; 48 import org.mortbay.util.LazyList; 49 import org.mortbay.util.MultiException; 50 import org.mortbay.util.MultiMap; 51 import org.mortbay.util.StringUtil; 52 import org.mortbay.util.TypeUtil; 53 54 55 64 public class WebApplicationHandler extends ServletHandler 65 { 66 private static Log log= LogFactory.getLog(WebApplicationHandler.class); 67 68 private Map _filterMap= new HashMap (); 69 private List _pathFilters= new ArrayList (); 70 private List _filters= new ArrayList (); 71 private MultiMap _servletFilterMap= new MultiMap(); 72 private boolean _acceptRanges= true; 73 private boolean _filterChainsCached=true; 74 75 private transient WebApplicationContext _webApplicationContext; 76 77 protected transient Object _requestListeners; 78 protected transient Object _requestAttributeListeners; 79 protected transient Object _sessionListeners; 80 protected transient Object _contextAttributeListeners; 81 protected transient FilterHolder jsr154FilterHolder; 82 protected transient JSR154Filter jsr154Filter; 83 protected transient HashMap _chainCache[]; 84 protected transient HashMap _namedChainCache[]; 85 86 87 public boolean isAcceptRanges() 88 { 89 return _acceptRanges; 90 } 91 92 93 97 public void setAcceptRanges(boolean ar) 98 { 99 _acceptRanges= ar; 100 } 101 102 103 106 public JSR154Filter getJsr154Filter() 107 { 108 return jsr154Filter; 109 } 110 111 112 public FilterHolder defineFilter(String name, String className) 113 { 114 FilterHolder holder= newFilterHolder(name,className); 115 addFilterHolder(holder); 116 return holder; 117 } 118 119 120 protected FilterHolder newFilterHolder(String name, String className) 121 { 122 return new FilterHolder(this, name, className); 123 } 124 125 126 public void addFilterHolder(FilterHolder holder) 127 { 128 _filterMap.put(holder.getName(), holder); 129 _filters.add(holder); 130 addComponent(holder); 131 } 132 133 134 public FilterHolder getFilter(String name) 135 { 136 return (FilterHolder)_filterMap.get(name); 137 } 138 139 140 147 public FilterHolder addFilterPathMapping(String pathSpec, String filterName, int dispatches) 148 { 149 FilterHolder holder = (FilterHolder)_filterMap.get(filterName); 150 if (holder==null) 151 throw new IllegalArgumentException ("unknown filter: "+filterName); 152 153 FilterMapping mapping = new FilterMapping(pathSpec,holder,dispatches); 154 _pathFilters.add(mapping); 155 return holder; 156 } 157 158 159 160 168 public FilterHolder addFilterServletMapping(String servletName, String filterName, int dispatches) 169 { 170 FilterHolder holder= (FilterHolder)_filterMap.get(filterName); 171 if (holder == null) 172 throw new IllegalArgumentException ("Unknown filter :" + filterName); 173 _servletFilterMap.add(servletName, new FilterMapping(null,holder,dispatches)); 174 return holder; 175 } 176 177 178 public List getFilters() 179 { 180 return _filters; 181 } 182 183 184 185 public synchronized void addEventListener(EventListener listener) 186 throws IllegalArgumentException 187 { 188 if ((listener instanceof HttpSessionActivationListener ) 189 || (listener instanceof HttpSessionAttributeListener ) 190 || (listener instanceof HttpSessionBindingListener ) 191 || (listener instanceof HttpSessionListener )) 192 { 193 if (_sessionManager != null) 194 _sessionManager.addEventListener(listener); 195 _sessionListeners= LazyList.add(_sessionListeners, listener); 196 } 197 198 if (listener instanceof ServletRequestListener ) 199 { 200 _requestListeners= LazyList.add(_requestListeners, listener); 201 } 202 203 if (listener instanceof ServletRequestAttributeListener ) 204 { 205 _requestAttributeListeners= LazyList.add(_requestAttributeListeners, listener); 206 } 207 208 if (listener instanceof ServletContextAttributeListener ) 209 { 210 _contextAttributeListeners= LazyList.add(_contextAttributeListeners, listener); 211 } 212 213 super.addEventListener(listener); 214 } 215 216 217 public synchronized void removeEventListener(EventListener listener) 218 { 219 if (_sessionManager != null) 220 _sessionManager.removeEventListener(listener); 221 222 _sessionListeners= LazyList.remove(_sessionListeners, listener); 223 _requestListeners= LazyList.remove(_requestListeners, listener); 224 _requestAttributeListeners= LazyList.remove(_requestAttributeListeners, listener); 225 _contextAttributeListeners= LazyList.remove(_contextAttributeListeners, listener); 226 super.removeEventListener(listener); 227 } 228 229 230 public void setSessionManager(SessionManager sm) 231 { 232 if (isStarted()) 233 throw new IllegalStateException ("Started"); 234 235 SessionManager old= getSessionManager(); 236 237 if (getHttpContext() != null) 238 { 239 if (old != null && old != sm) 241 { 242 if (_sessionListeners != null) 243 { 244 for (Iterator i= LazyList.iterator(_sessionListeners); i.hasNext();) 245 { 246 EventListener listener= (EventListener )i.next(); 247 _sessionManager.removeEventListener(listener); 248 } 249 } 250 } 251 252 if (sm != null && old != sm) 254 { 255 if (_sessionListeners != null) 256 { 257 for (Iterator i= LazyList.iterator(_sessionListeners); i.hasNext();) 258 { 259 EventListener listener= (EventListener )i.next(); 260 sm.addEventListener(listener); 261 } 262 } 263 } 264 } 265 266 super.setSessionManager(sm); 267 } 268 269 270 protected synchronized void doStart() throws Exception 271 { 272 super.doStart(); 274 if (log.isDebugEnabled()) 275 log.debug("Path Filters: " + _pathFilters); 276 if (log.isDebugEnabled()) 277 log.debug("Servlet Filters: " + _servletFilterMap); 278 279 if (getHttpContext() instanceof WebApplicationContext) 280 _webApplicationContext= (WebApplicationContext)getHttpContext(); 281 282 if (_filterChainsCached) 283 { 284 _chainCache = getChainCache(); 285 _namedChainCache = getChainCache(); 286 } 287 } 288 289 290 private HashMap [] getChainCache() { 291 HashMap [] _chainCache=new HashMap [Dispatcher.__ERROR+1]; 292 _chainCache[Dispatcher.__REQUEST]=new HashMap (); 293 _chainCache[Dispatcher.__FORWARD]=new HashMap (); 294 _chainCache[Dispatcher.__INCLUDE]=new HashMap (); 295 _chainCache[Dispatcher.__ERROR]=new HashMap (); 296 return _chainCache; 297 } 298 299 300 public void initializeServlets() throws Exception 301 { 302 MultiException mex= new MultiException(); 304 Iterator iter= _filters.iterator(); 305 while (iter.hasNext()) 306 { 307 FilterHolder holder= (FilterHolder)iter.next(); 308 try 309 { 310 holder.start(); 311 } 312 catch (Exception e) 313 { 314 mex.add(e); 315 } 316 } 317 318 try 320 { 321 super.initializeServlets(); 322 } 323 catch (Exception e) 324 { 325 mex.add(e); 326 } 327 328 jsr154FilterHolder=getFilter("jsr154"); 329 if (jsr154FilterHolder!=null) 330 jsr154Filter= (JSR154Filter)jsr154FilterHolder.getFilter(); 331 log.debug("jsr154filter="+jsr154Filter); 332 333 if (LazyList.size(_requestAttributeListeners) > 0 || LazyList.size(_requestListeners) > 0) 334 { 335 336 if (jsr154Filter==null) 337 log.warn("Filter jsr154 not defined for RequestAttributeListeners"); 338 else 339 { 340 jsr154Filter.setRequestAttributeListeners(_requestAttributeListeners); 341 jsr154Filter.setRequestListeners(_requestListeners); 342 } 343 } 344 345 mex.ifExceptionThrow(); 346 } 347 348 349 protected synchronized void doStop() throws Exception 350 { 351 try 352 { 353 super.doStop(); 355 356 for (int i= _filters.size(); i-- > 0;) 358 { 359 FilterHolder holder= (FilterHolder)_filters.get(i); 360 holder.stop(); 361 } 362 } 363 finally 364 { 365 _webApplicationContext= null; 366 _sessionListeners= null; 367 _requestListeners= null; 368 _requestAttributeListeners= null; 369 _contextAttributeListeners= null; 370 } 371 } 372 373 374 public String getErrorPage(int status, ServletHttpRequest request) 375 { 376 String error_page= null; 377 Class exClass= (Class )request.getAttribute(ServletHandler.__J_S_ERROR_EXCEPTION_TYPE); 378 379 if (ServletException .class.equals(exClass)) 380 { 381 error_page= _webApplicationContext.getErrorPage(exClass.getName()); 382 if (error_page == null) 383 { 384 Throwable th= (Throwable )request.getAttribute(ServletHandler.__J_S_ERROR_EXCEPTION); 385 while (th instanceof ServletException ) 386 th= ((ServletException )th).getRootCause(); 387 if (th != null) 388 exClass= th.getClass(); 389 } 390 } 391 392 if (error_page == null && exClass != null) 393 { 394 while (error_page == null && exClass != null && _webApplicationContext != null) 395 { 396 error_page= _webApplicationContext.getErrorPage(exClass.getName()); 397 exClass= exClass.getSuperclass(); 398 } 399 400 if (error_page == null) 401 {} 402 } 403 404 if (error_page == null && _webApplicationContext != null) 405 error_page= _webApplicationContext.getErrorPage(TypeUtil.toString(status)); 406 407 return error_page; 408 } 409 410 411 protected void dispatch(String pathInContext, 412 HttpServletRequest request, 413 HttpServletResponse response, 414 ServletHolder servletHolder, 415 int type) 416 throws ServletException , UnavailableException , IOException 417 { 418 if (type == Dispatcher.__REQUEST) 419 { 420 ServletHttpRequest servletHttpRequest= (ServletHttpRequest)request; 422 ServletHttpResponse servletHttpResponse= (ServletHttpResponse)response; 423 424 if (StringUtil.startsWithIgnoreCase(pathInContext, "/web-inf") || StringUtil.startsWithIgnoreCase(pathInContext, "/meta-inf")) 426 { 427 response.sendError(HttpResponse.__404_Not_Found); 428 return; 429 } 430 431 if (!getHttpContext().checkSecurityConstraints( 433 pathInContext, 434 servletHttpRequest.getHttpRequest(), 435 servletHttpResponse.getHttpResponse())) 436 return; 437 } 438 else 439 { 440 442 HttpContext context= getHttpContext(); 444 if (context != null 445 && context instanceof ServletHttpContext 446 && pathInContext != null 447 && pathInContext.endsWith(FormAuthenticator.__J_SECURITY_CHECK)) 448 { 449 ServletHttpRequest servletHttpRequest= 450 (ServletHttpRequest)context.getHttpConnection().getRequest().getWrapper(); 451 ServletHttpResponse servletHttpResponse= servletHttpRequest.getServletHttpResponse(); 452 ServletHttpContext servletContext= (ServletHttpContext)context; 453 454 if (!servletContext.jSecurityCheck(pathInContext,servletHttpRequest.getHttpRequest(),servletHttpResponse.getHttpResponse())) 455 return; 456 } 457 } 458 459 FilterChain chain=null; 461 if (pathInContext != null) { 462 chain = getChainForPath(type, pathInContext, servletHolder); 463 } else { 464 chain = getChainForName(type, servletHolder); 465 } 466 467 if (log.isDebugEnabled()) log.debug("chain="+chain); 468 469 if (chain!=null) 471 chain.doFilter(request, response); 472 else if (servletHolder != null) 473 servletHolder.handle(request, response); 474 else notFound(request, response); 476 } 477 478 479 private FilterChain getChainForName(int requestType, ServletHolder servletHolder) { 480 if (servletHolder == null) { 481 throw new IllegalStateException ("Named dispatch must be to an explicitly named servlet"); 482 } 483 484 if (_filterChainsCached) 485 { 486 synchronized(this) 487 { 488 if (_namedChainCache[requestType].containsKey(servletHolder.getName())) 489 return (FilterChain )_namedChainCache[requestType].get(servletHolder.getName()); 490 } 491 } 492 493 Object filters= null; 495 496 if (jsr154Filter!=null) 497 { 498 filters=LazyList.add(filters,jsr154FilterHolder); 501 } 502 503 if (_servletFilterMap.size() > 0) 505 { 506 Object o= _servletFilterMap.get(servletHolder.getName()); 507 for (int i=0; i<LazyList.size(o);i++) 508 { 509 FilterMapping mapping = (FilterMapping)LazyList.get(o,i); 510 if (mapping.appliesTo(null,requestType)) 511 filters=LazyList.add(filters,mapping.getHolder()); 512 } 513 } 514 515 FilterChain chain = null; 516 if (_filterChainsCached) 517 { 518 synchronized(this) 519 { 520 if (LazyList.size(filters) > 0) 521 chain= new CachedChain(filters, servletHolder); 522 _namedChainCache[requestType].put(servletHolder.getName(),chain); 523 } 524 } 525 else if (LazyList.size(filters) > 0) 526 chain = new Chain (filters, servletHolder); 527 528 return chain; 529 } 530 531 532 private FilterChain getChainForPath(int requestType, String pathInContext, ServletHolder servletHolder) 533 { 534 if (_filterChainsCached) 535 { 536 synchronized(this) 537 { 538 if(_chainCache[requestType].containsKey(pathInContext)) 539 return (FilterChain )_chainCache[requestType].get(pathInContext); 540 } 541 } 542 543 Object filters= null; 545 546 for (int i= 0; i < _pathFilters.size(); i++) 548 { 549 FilterMapping mapping = (FilterMapping)_pathFilters.get(i); 550 if (mapping.appliesTo(pathInContext, requestType)) 551 filters= LazyList.add(filters, mapping.getHolder()); 552 } 553 554 if (servletHolder != null && _servletFilterMap.size() > 0) 556 { 557 Object o= _servletFilterMap.get(servletHolder.getName()); 558 for (int i=0; i<LazyList.size(o);i++) 559 { 560 FilterMapping mapping = (FilterMapping)LazyList.get(o,i); 561 if (mapping.appliesTo(null,requestType)) 562 filters=LazyList.add(filters,mapping.getHolder()); 563 } 564 } 565 566 FilterChain chain = null; 567 if (_filterChainsCached) 568 { 569 synchronized(this) 570 { 571 if (LazyList.size(filters) > 0) 572 chain= new CachedChain(filters, servletHolder); 573 _chainCache[requestType].put(pathInContext,chain); 574 } 575 } 576 else if (LazyList.size(filters) > 0) 577 chain = new Chain (filters, servletHolder); 578 579 return chain; 580 } 581 582 583 584 public synchronized void setContextAttribute(String name, Object value) 585 { 586 Object old= super.getContextAttribute(name); 587 super.setContextAttribute(name, value); 588 589 if (_contextAttributeListeners != null) 590 { 591 ServletContextAttributeEvent event= 592 new ServletContextAttributeEvent (getServletContext(), name, old != null ? old : value); 593 for (int i= 0; i < LazyList.size(_contextAttributeListeners); i++) 594 { 595 ServletContextAttributeListener l= 596 (ServletContextAttributeListener )LazyList.get(_contextAttributeListeners, i); 597 if (old == null) 598 l.attributeAdded(event); 599 else 600 if (value == null) 601 l.attributeRemoved(event); 602 else 603 l.attributeReplaced(event); 604 } 605 } 606 } 607 608 609 public synchronized void removeContextAttribute(String name) 610 { 611 Object old= super.getContextAttribute(name); 612 super.removeContextAttribute(name); 613 614 if (old != null && _contextAttributeListeners != null) 615 { 616 ServletContextAttributeEvent event= new ServletContextAttributeEvent (getServletContext(), name, old); 617 for (int i= 0; i < LazyList.size(_contextAttributeListeners); i++) 618 { 619 ServletContextAttributeListener l= 620 (ServletContextAttributeListener )LazyList.get(_contextAttributeListeners, i); 621 l.attributeRemoved(event); 622 } 623 } 624 } 625 626 627 630 public boolean isFilterChainsCached() 631 { 632 return _filterChainsCached; 633 } 634 635 636 642 public void setFilterChainsCached(boolean filterChainsCached) 643 { 644 _filterChainsCached = filterChainsCached; 645 } 646 647 648 651 protected void addComponent(Object o) 652 { 653 if (_filterChainsCached && isStarted()) 654 { 655 synchronized(this) 656 { 657 for (int i=0;i<_chainCache.length;i++) 658 if (_chainCache[i]!=null) 659 _chainCache[i].clear(); 660 } 661 } 662 super.addComponent(o); 663 } 664 665 666 669 protected void removeComponent(Object o) 670 { 671 if (_filterChainsCached && isStarted()) 672 { 673 synchronized(this) 674 { 675 for (int i=0;i<_chainCache.length;i++) 676 if (_chainCache[i]!=null) 677 _chainCache[i].clear(); 678 } 679 } 680 super.removeComponent(o); 681 } 682 683 684 public void destroy() 685 { 686 Iterator iter = _filterMap.values().iterator(); 687 while (iter.hasNext()) 688 { 689 Object sh=iter.next(); 690 iter.remove(); 691 removeComponent(sh); 692 } 693 } 694 695 696 697 private static class FilterMapping 698 { 699 private String _pathSpec; 700 private FilterHolder _holder; 701 private int _dispatches; 702 703 704 FilterMapping(String pathSpec,FilterHolder holder,int dispatches) 705 { 706 _pathSpec=pathSpec; 707 _holder=holder; 708 _dispatches=dispatches; 709 } 710 711 712 FilterHolder getHolder() 713 { 714 return _holder; 715 } 716 717 718 723 boolean appliesTo(String path, int type) 724 { 725 boolean b=((_dispatches&type)!=0 || (_dispatches==0 && type==Dispatcher.__REQUEST)) && (_pathSpec==null || PathMap.match(_pathSpec, path,true)); 726 return b; 727 } 728 } 729 730 731 732 733 734 private class Chain implements FilterChain 735 { 736 int _filter= 0; 737 Object _filters; 738 ServletHolder _servletHolder; 739 740 741 Chain(Object filters, ServletHolder servletHolder) 742 { 743 _filters= filters; 744 _servletHolder= servletHolder; 745 } 746 747 748 public void doFilter(ServletRequest request, ServletResponse response) 749 throws IOException , ServletException 750 { 751 if (log.isTraceEnabled()) 752 log.trace("doFilter " + _filter); 753 754 if (_filter < LazyList.size(_filters)) 756 { 757 FilterHolder holder= (FilterHolder)LazyList.get(_filters, _filter++); 758 if (log.isTraceEnabled()) 759 log.trace("call filter " + holder); 760 Filter filter= holder.getFilter(); 761 filter.doFilter(request, response, this); 762 return; 763 } 764 765 if (_servletHolder != null) 767 { 768 if (log.isTraceEnabled()) 769 log.trace("call servlet " + _servletHolder); 770 _servletHolder.handle(request, response); 771 } 772 else notFound((HttpServletRequest )request, (HttpServletResponse )response); 774 } 775 776 public String toString() 777 { 778 StringBuffer b = new StringBuffer (); 779 for (int i=0; i<LazyList.size(_filters);i++) 780 { 781 b.append(LazyList.get(_filters, i).toString()); 782 b.append("->"); 783 } 784 b.append(_servletHolder); 785 return b.toString(); 786 } 787 } 788 789 790 791 792 793 private class CachedChain implements FilterChain 794 { 795 FilterHolder _filterHolder; 796 ServletHolder _servletHolder; 797 CachedChain _next; 798 799 800 CachedChain(Object filters, ServletHolder servletHolder) 801 { 802 if (LazyList.size(filters)>0) 803 { 804 _filterHolder=(FilterHolder)LazyList.get(filters, 0); 805 filters=LazyList.remove(filters,0); 806 _next=new CachedChain(filters,servletHolder); 807 } 808 else 809 _servletHolder=servletHolder; 810 } 811 812 public void doFilter(ServletRequest request, ServletResponse response) 813 throws IOException , ServletException 814 { 815 if (_filterHolder!=null) 817 { 818 if (log.isTraceEnabled()) 819 log.trace("call filter " + _filterHolder); 820 Filter filter= _filterHolder.getFilter(); 821 filter.doFilter(request, response, _next); 822 return; 823 } 824 825 if (_servletHolder != null) 827 { 828 if (log.isTraceEnabled()) 829 log.trace("call servlet " + _servletHolder); 830 _servletHolder.handle(request, response); 831 } 832 else notFound((HttpServletRequest )request, (HttpServletResponse )response); 834 } 835 836 public String toString() 837 { 838 if (_filterHolder!=null) 839 return _filterHolder+"->"+_next.toString(); 840 if (_servletHolder!=null) 841 return _servletHolder.toString(); 842 return "null"; 843 } 844 } 845 846 847 public static void main(String [] arg) 848 { 849 850 ServletHandler mServletHandler = new ServletHandler(); 851 852 ServletHolder servletHolder = mServletHandler.addServlet("/mPath", 853 "wicket.protocol.http.WicketServlet"); 854 servletHolder.getServletContext().setAttribute("webApplication", "mWebApplication"); 855 servletHolder.getServletContext().setAttribute ("applicationContext", "mApplicationContext"); 856 857 WebApplicationHandler mWebApplicationHandler = new WebApplicationHandler(); 858 859 ServletHolder servletHolder2 = mWebApplicationHandler.addServlet("/mpath", 860 "wicket.protocol.http.WicketServlet"); 861 servletHolder2.getServletContext().setAttribute("webApplication", "mWebApplication"); 862 servletHolder2.getServletContext().setAttribute ("applicationContext", "mApplicationContext"); 863 864 } 865 } 866 | Popular Tags |