1 29 30 package com.caucho.server.dispatch; 31 32 import com.caucho.config.BuilderProgram; 33 import com.caucho.config.Config; 34 import com.caucho.config.NodeBuilderProgram; 35 import com.caucho.config.types.InitParam; 36 import com.caucho.config.types.InitProgram; 37 import com.caucho.jmx.Jmx; 38 import com.caucho.jsp.Page; 39 import com.caucho.jsp.QServlet; 40 import com.caucho.naming.Jndi; 41 import com.caucho.server.connection.StubServletRequest; 42 import com.caucho.server.connection.StubServletResponse; 43 import com.caucho.soa.servlet.ProtocolServlet; 44 import com.caucho.soa.servlet.SoapProtocolServlet; 45 import com.caucho.util.Alarm; 46 import com.caucho.util.AlarmListener; 47 import com.caucho.util.CompileException; 48 import com.caucho.util.L10N; 49 import com.caucho.util.Log; 50 51 import javax.annotation.PostConstruct; 52 import javax.jws.WebService; 53 import javax.naming.NamingException ; 54 import javax.servlet.*; 55 import java.lang.reflect.Constructor ; 56 import java.lang.reflect.Modifier ; 57 import java.util.Collections ; 58 import java.util.Enumeration ; 59 import java.util.HashMap ; 60 import java.util.Hashtable ; 61 import java.util.Map ; 62 import java.util.logging.Level ; 63 import java.util.logging.Logger ; 64 65 68 public class ServletConfigImpl implements ServletConfig, AlarmListener { 69 static L10N L = new L10N(ServletConfigImpl.class); 70 protected static final Logger log = Log.open(ServletConfigImpl.class); 71 72 private String _location; 73 74 private String _jndiName; 75 private String _var; 76 77 private String _servletName; 78 private String _servletClassName; 79 private Class _servletClass; 80 private String _jspFile; 81 private String _displayName; 82 private int _loadOnStartup = Integer.MIN_VALUE; 83 84 private boolean _allowEL = true; 85 private HashMap <String ,String > _initParams = new HashMap <String ,String >(); 86 87 private HashMap <String ,String > _roleMap; 88 89 private InitProgram _init; 90 91 private RunAt _runAt; 92 93 private Class _protocolClass; 94 private BuilderProgram _protocolInit; 95 96 private Alarm _alarm; 97 98 private ServletContext _servletContext; 99 private ServletManager _servletManager; 100 101 private ServletException _initException; 102 private long _nextInitTime; 103 104 private Object _servlet; 105 private FilterChain _servletChain; 106 107 110 public ServletConfigImpl() 111 { 112 } 113 114 117 public void setConfigLocation(String location, int line) 118 { 119 _location = location + ":" + line + ": "; 120 } 121 122 125 public void setId(String id) 126 { 127 } 128 129 132 public void setServletName(String name) 133 { 134 _servletName = name; 135 } 136 137 140 public String getServletName() 141 { 142 return _servletName; 143 } 144 145 148 public String getServletClassName() 149 { 150 return _servletClassName; 151 } 152 153 156 public void setServletClass(String servletClassName) 157 throws ServletException 158 { 159 _servletClassName = servletClassName; 160 } 161 162 165 public Class getServletClass() 166 { 167 return _servletClass; 168 } 169 170 173 public void setJspFile(String jspFile) 174 { 175 _jspFile = jspFile; 176 } 177 178 181 public String getJspFile() 182 { 183 return _jspFile; 184 } 185 186 189 public void setAllowEL(boolean allowEL) 190 { 191 _allowEL = allowEL; 192 } 193 194 197 public void setInitParam(String param, String value) 198 { 199 _initParams.put(param, value); 200 } 201 202 205 public InitParam createInitParam() 206 { 207 InitParam initParam = new InitParam(); 208 209 initParam.setAllowEL(_allowEL); 210 211 return initParam; 212 } 213 214 217 public void setInitParam(InitParam initParam) 218 { 219 _initParams.putAll(initParam.getParameters()); 220 } 221 222 225 public Map getInitParamMap() 226 { 227 return _initParams; 228 } 229 230 233 public String getInitParameter(String name) 234 { 235 return _initParams.get(name); 236 } 237 238 241 public Enumeration getInitParameterNames() 242 { 243 return Collections.enumeration(_initParams.keySet()); 244 } 245 246 249 public ServletContext getServletContext() 250 { 251 return _servletContext; 252 } 253 254 257 public void setServletContext(ServletContext app) 258 { 259 _servletContext = app; 260 } 261 262 265 public ServletManager getServletManager() 266 { 267 return _servletManager; 268 } 269 270 273 public void setServletManager(ServletManager manager) 274 { 275 _servletManager = manager; 276 } 277 278 281 public void setInit(InitProgram init) 282 { 283 _init = init; 284 } 285 286 289 public InitProgram getInit() 290 { 291 return _init; 292 } 293 294 297 public void setLoadOnStartup(int loadOnStartup) 298 { 299 _loadOnStartup = loadOnStartup; 300 } 301 302 305 public int getLoadOnStartup() 306 { 307 if (_loadOnStartup > Integer.MIN_VALUE) 308 return _loadOnStartup; 309 else if (_runAt != null) 310 return 0; 311 else 312 return Integer.MIN_VALUE; 313 } 314 315 318 public RunAt createRunAt() 319 { 320 if (_runAt == null) 321 _runAt = new RunAt(); 322 323 return _runAt; 324 } 325 326 public void setJndiName(String jndiName) 327 { 328 _jndiName = jndiName; 329 } 330 331 public void setVar(String var) 332 { 333 _var = var; 334 } 335 336 339 public RunAt getRunAt() 340 { 341 return _runAt; 342 } 343 344 347 public void addSecurityRoleRef(SecurityRoleRef ref) 348 { 349 if (_roleMap == null) 350 _roleMap = new HashMap <String ,String >(); 351 352 _roleMap.put(ref.getRoleName(), ref.getRoleLink()); 355 } 356 357 360 public HashMap <String ,String > getRoleMap() 361 { 362 return _roleMap; 363 } 364 365 368 public void setDisplayName(String displayName) 369 { 370 _displayName = displayName; 371 } 372 373 376 public String getDisplayName() 377 { 378 return _displayName; 379 } 380 381 384 public void setDescription(String description) 385 { 386 } 387 388 391 public void setIcon(com.caucho.config.types.Icon icon) 392 { 393 } 394 395 398 public void setProtocol(ServletProtocolConfig protocol) 399 { 400 _protocolClass = protocol.getType(); 401 _protocolInit = protocol.getProgram(); 402 } 403 404 407 public void setInitException(ServletException exn) 408 { 409 _initException = exn; 410 411 _nextInitTime = Long.MAX_VALUE / 2; 412 413 if (exn instanceof UnavailableException) { 414 UnavailableException unExn = (UnavailableException) exn; 415 416 if (! unExn.isPermanent()) 417 _nextInitTime = (Alarm.getCurrentTime() + 418 1000L * unExn.getUnavailableSeconds()); 419 } 420 } 421 422 425 public Object getServlet() 426 { 427 return _servlet; 428 } 429 430 433 @PostConstruct 434 public void init() 435 throws ServletException 436 { 437 if (_runAt != null) { 438 _alarm = new Alarm(this); 439 } 440 441 if (_servletName != null) { 442 } 443 else if (_protocolClass != null) { 444 String protocol = _protocolClass.getName(); 445 446 int p = protocol.lastIndexOf('.'); 447 protocol = protocol.substring(p + 1); 448 449 _servletName = _servletClassName + "-" + protocol; 450 } 451 else 452 _servletName = _servletClassName; 453 454 if (_jndiName != null) { 456 validateClass(true); 457 458 Object servlet = createServlet(false); 459 460 try { 461 Jndi.bindDeepShort(_jndiName, servlet); 462 } catch (NamingException e) { 463 throw new ServletException(e); 464 } 465 } 466 467 if (_var != null) { 468 validateClass(true); 469 470 Object servlet = createServlet(false); 471 472 Config.setCurrentVar(_var, servlet); 473 } 474 } 475 476 protected void validateClass(boolean requireClass) 477 throws ServletException 478 { 479 if (_runAt != null || _loadOnStartup >= 0) 480 requireClass = true; 481 482 Thread thread = Thread.currentThread(); 483 ClassLoader loader = thread.getContextClassLoader(); 484 485 if (_servletClassName == null) { 486 } 487 else if (_servletClassName.equals("invoker")) { 488 } 489 else { 490 try { 491 _servletClass = Class.forName(_servletClassName, false, loader); 492 } catch (ClassNotFoundException e) { 493 if (e instanceof CompileException) 494 throw error(e); 495 496 log.log(Level.FINER, e.toString(), e); 497 } 498 499 if (_servletClass != null) { 500 } 501 else if (requireClass) { 502 throw error(L.l("'{0}' is not a known servlet. Servlets belong in the classpath, often in WEB-INF/classes.", _servletClassName)); 503 } 504 else { 505 String location = _location != null ? _location : ""; 506 507 log.warning(L.l(location + "'{0}' is not a known servlet. Servlets belong in the classpath, often in WEB-INF/classes.", _servletClassName)); 508 return; 509 } 510 511 Config.checkCanInstantiate(_servletClass); 512 513 if (_servletClass.isAnnotationPresent(WebService.class)) { 514 if (_protocolClass == null) 515 _protocolClass = SoapProtocolServlet.class; 516 } 517 else if (Servlet.class.isAssignableFrom(_servletClass)) { 518 } 519 else 520 throw error(L.l("'{0}' must implement javax.servlet.Servlet or have a @WebService annotation. All servlets must implement the Servlet interface.", _servletClassName)); 521 522 531 } 532 } 533 534 537 public void checkConstructor() 538 throws ServletException 539 { 540 Constructor []constructors = _servletClass.getDeclaredConstructors(); 541 542 Constructor zeroArg = null; 543 for (int i = 0; i < constructors.length; i++) { 544 if (constructors[i].getParameterTypes().length == 0) { 545 zeroArg = constructors[i]; 546 break; 547 } 548 } 549 550 if (zeroArg == null) 551 throw error(L.l("'{0}' must have a zero arg constructor. Servlets must have public zero-arg constructors.\n{1} is not a valid constructor.", _servletClassName, constructors[0])); 552 553 554 if (! Modifier.isPublic(zeroArg.getModifiers())) 555 throw error(L.l("'{0}' must be public. '{1}' must have a public, zero-arg constructor.", 556 zeroArg, 557 _servletClassName)); 558 } 559 560 563 public void handleAlarm(Alarm alarm) 564 { 565 try { 566 log.fine(this + " cron"); 567 568 FilterChain chain = createServletChain(); 569 570 ServletRequest req = new StubServletRequest(); 571 ServletResponse res = new StubServletResponse(); 572 573 chain.doFilter(req, res); 574 } catch (Throwable e) { 575 log.log(Level.WARNING, e.toString(), e); 576 } finally { 577 long nextTime = _runAt.getNextTimeout(Alarm.getCurrentTime()); 578 _alarm.queue(nextTime - Alarm.getCurrentTime()); 579 } 580 } 581 582 public FilterChain createServletChain() 583 throws ServletException 584 { 585 synchronized (this) { 586 588 if (_servletChain != null) 589 return _servletChain; 590 else 591 return createServletChainImpl(); 592 } 593 } 594 595 private FilterChain createServletChainImpl() 596 throws ServletException 597 { 598 String jspFile = getJspFile(); 599 FilterChain servletChain = null; 600 601 if (jspFile != null) { 602 QServlet jsp = (QServlet) _servletManager.createServlet("resin-jsp"); 603 604 servletChain = new PageFilterChain(_servletContext, jsp, jspFile, this); 605 606 return servletChain; 607 } 608 609 validateClass(true); 610 611 Class servletClass = getServletClass(); 612 613 if (servletClass == null) { 614 throw new IllegalStateException (L.l("servlet class for {0} can't be null", 615 getServletName())); 616 } 617 else if (QServlet.class.isAssignableFrom(servletClass)) { 618 servletChain = new PageFilterChain(_servletContext, (QServlet) createServlet(false)); 619 } 620 else if (SingleThreadModel.class.isAssignableFrom(servletClass)) { 621 servletChain = new SingleThreadServletFilterChain(this); 622 } 623 else if (servletClass.isAnnotationPresent(WebService.class)) 624 servletChain = new WebServiceFilterChain(this); 625 else { 626 servletChain = new ServletFilterChain(this); 627 } 628 629 if (_roleMap != null) 630 servletChain = new SecurityRoleMapFilterChain(servletChain, _roleMap); 631 632 638 639 return servletChain; 640 } 641 642 647 ProtocolServlet createWebServiceSkeleton() 648 throws ServletException 649 { 650 try { 651 Object service = createServlet(false); 652 653 ProtocolServlet skeleton 654 = (ProtocolServlet) _protocolClass.newInstance(); 655 656 skeleton.setService(service); 657 658 if (_protocolInit != null) { 659 _protocolInit.configure(skeleton); 660 } 661 662 skeleton.init(this); 663 664 return skeleton; 665 } catch (RuntimeException e) { 666 throw e; 667 } catch (ServletException e) { 668 throw e; 669 } catch (Exception e) { 670 throw new ServletException(e); 671 } 672 } 673 674 681 Object createServlet(boolean isNew) 682 throws ServletException 683 { 684 if (_servlet != null && ! isNew) 686 return _servlet; 687 688 Object servlet = null; 689 690 if (Alarm.getCurrentTime() < _nextInitTime) 691 throw _initException; 692 693 if (log.isLoggable(Level.FINE)) 694 log.fine("Servlet[" + _servletName + "] starting"); 695 696 try { 697 servlet = createServletImpl(); 698 699 synchronized (this) { 700 if (_servlet == null && ! isNew) 701 _servlet = servlet; 702 } 703 704 706 if (_servlet == servlet) { 707 try { 709 Hashtable <String ,String > props = new Hashtable <String ,String >(); 710 711 String className = _servlet.getClass().getName(); 712 int p = className.lastIndexOf('.'); 713 props.put("type", className.substring(p + 1)); 714 props.put("name", _servletName); 715 Jmx.register(_servlet, props); 716 } catch (Exception e) { 717 log.finest(e.toString()); 718 } 719 720 if (_runAt != null && _alarm != null) { 721 long nextTime = _runAt.getNextTimeout(Alarm.getCurrentTime()); 722 _alarm.queue(nextTime - Alarm.getCurrentTime()); 723 } 724 } 725 726 if (log.isLoggable(Level.FINER)) 727 log.finer("Servlet[" + _servletName + "] started"); 728 729 return servlet; 730 } catch (ServletException e) { 731 throw e; 732 } catch (Throwable e) { 733 log.log(Level.WARNING, e.toString(), e); 734 735 throw new ServletException(e); 736 } 737 } 738 739 private Object createServletImpl() 740 throws Throwable 741 { 742 Class servletClass = getServletClass(); 743 744 Object servlet; 745 if (_jspFile != null) { 746 servlet = createJspServlet(_servletName, _jspFile); 747 748 if (servlet == null) 749 throw new ServletException(L.l("'{0}' is a missing JSP file.", 750 _jspFile)); 751 } 752 753 else if (servletClass != null) 754 servlet = servletClass.newInstance(); 755 756 else 757 throw new ServletException(L.l("Null servlet class for '{0}'.", 758 _servletName)); 759 760 configureServlet(servlet); 761 762 try { 763 if (servlet instanceof Servlet) { 764 Servlet servletObj = (Servlet) servlet; 765 766 servletObj.init(this); 767 } 768 } catch (UnavailableException e) { 769 setInitException(e); 770 throw e; 771 } 772 773 return servlet; 774 } 775 776 780 void configureServlet(Object servlet) 781 throws Throwable 782 { 783 785 InitProgram init = getInit(); 787 BuilderProgram program; 788 789 if (init != null) 790 program = init.getBuilderProgram(); 791 else 792 program = NodeBuilderProgram.NULL; 793 794 program.configure(servlet); 795 program.init(servlet); 796 } 797 798 805 private Servlet createJspServlet(String servletName, String jspFile) 806 throws ServletException 807 { 808 try { 809 ServletConfigImpl jspConfig = _servletManager.getServlet("resin-jsp"); 810 811 QServlet jsp = (QServlet) jspConfig.createServlet(false); 812 813 Page page = jsp.getPage(servletName, jspFile); 814 815 return page; 816 } catch (ServletException e) { 817 throw e; 818 } catch (Exception e) { 819 throw new ServletException(e); 820 } 821 } 822 823 void killServlet() 824 { 825 Object servlet = _servlet; 826 _servlet = null; 827 828 if (_alarm != null) 829 _alarm.dequeue(); 830 831 if (servlet instanceof Servlet) { 832 ((Servlet) servlet).destroy(); 833 } 834 } 835 836 public void close() 837 { 838 killServlet(); 839 840 _alarm = null; 841 } 842 843 protected ServletException error(String msg) 844 { 845 if (_location != null) 846 return new ServletLineConfigException(_location + msg); 847 else 848 return new ServletConfigException(msg); 849 } 850 851 protected ServletException error(Throwable e) 852 { 853 if (_location != null) 854 return new ServletLineConfigException(_location + e.getMessage(), e); 855 else 856 return new ServletConfigException(e); 857 } 858 859 862 public String toString() 863 { 864 return "ServletConfigImpl[name=" + _servletName + ",class=" + _servletClass + "]"; 865 } 866 } 867 | Popular Tags |