1 23 24 25 26 27 28 package com.lutris.appserver.server.httpPresentation.servlet; 29 30 import java.io.File ; 31 import java.io.IOException ; 32 import java.io.PrintWriter ; 33 import java.lang.reflect.Constructor ; 34 import java.util.regex.Pattern ; 35 36 import javax.servlet.ServletConfig ; 37 import javax.servlet.ServletContext ; 38 import javax.servlet.ServletException ; 39 import javax.servlet.ServletRequest ; 40 import javax.servlet.http.HttpServlet ; 41 import javax.servlet.http.HttpServletRequest ; 42 import javax.servlet.http.HttpServletResponse ; 43 44 import org.apache.axis.transport.http.AxisServlet; 45 import org.enhydra.server.EnhydraServer; 46 import org.enhydra.util.ConfigFileInterface; 47 48 import com.lutris.appserver.server.Application; 49 import com.lutris.appserver.server.ApplicationException; 50 import com.lutris.appserver.server.Enhydra; 51 import com.lutris.appserver.server.httpPresentation.HttpPresentationException; 52 import com.lutris.appserver.server.httpPresentation.HttpPresentationManager; 53 import com.lutris.appserver.server.httpPresentation.HttpPresentationRequest; 54 import com.lutris.appserver.server.httpPresentation.HttpPresentationResponse; 55 import com.lutris.appserver.server.session.Session; 56 import com.lutris.classloader.MultiClassLoader; 57 import com.lutris.logging.LogChannel; 58 import com.lutris.logging.Logger; 59 import com.lutris.util.Config; 60 61 102 public class HttpPresentationServlet extends HttpServlet { 105 106 109 public static final String XMLC_DOM_STATS_LOG_LEVEL = "XMLC_DOM_STATS"; 110 111 114 protected ServletContext context; 115 116 119 private static final String APP_CONFIG_INIT_PARAM_NAME = 120 EnhydraServer.CONF_FILE; 121 private static final String APP_CONFIG_FILE_CLASS = 122 EnhydraServer.CONF_FILE_CLASS; private static final String APP_CLASS_PATH_FIELD = 124 EnhydraServer.SERVER + "." + EnhydraServer.CLASS_PATH; 125 private static final String APP_APP_CLASS_FIELD = 126 EnhydraServer.SERVER + "." + EnhydraServer.APP_CLASS; 127 private static final String APP_PRESENTATION_PREFIX_FIELD = 128 EnhydraServer.SERVER + "." + EnhydraServer.PRESENTATION_PREFIX; 129 private static final String APP_AUTO_RELOAD_FIELD = 130 EnhydraServer.SERVER + "." + EnhydraServer.AUTO_RELOAD; 131 private static final String APP_DEFERRED_PARSING_FIELD = 132 EnhydraServer.SERVER + ".XMLC.DeferredParsing"; private static final String APP_JIVAN_RELOAD_FIELD = 134 EnhydraServer.SERVER + ".AutoReload"; private static final String APP_ENCODING_TYPE = 136 EnhydraServer.APPLICATION + "." + "Encoding"; 137 private static final String APP_PRESENTATION_TOOLS = 138 EnhydraServer.APPLICATION + ".PresentationTools"; 140 141 144 private LogChannel logChannel; 145 146 150 private Logger standardLogger; 151 152 156 private boolean needToConfigureLogChannel = true; 157 158 159 162 String characterEncoding; 163 private boolean needToSetCharacterEncoding = false; 164 165 168 Application application = null; 169 Config appConfig = null; 170 String presentationPrefix; 171 String logClassName; 172 boolean cacheClasses; 173 boolean cacheFiles; 174 boolean autoReload; 176 HttpPresentationManager presentationManager = null; 177 178 private boolean isMemoryPersistence = false; 180 private String appName = null; 182 185 private PrintWriter domStatsLogWriter; 186 private AxisServlet axisServlet = null; 187 private Pattern axisPattern = Pattern.compile(".*Axis.*"); 188 189 private MultiClassLoader appClassLoader = null; 191 194 public HttpPresentationServlet() { 195 super(); 196 } 197 198 201 private void throwServletException(String msg, Throwable cause) throws 202 ServletException { 203 if (logChannel != null) { 204 logChannel.write(Logger.ERROR, msg, cause); 205 } 206 else { 207 System.err.println("Error: " + msg); 209 cause.printStackTrace(); 210 } 211 throw new ServletException (msg + "\ncaused by " 212 + cause.getClass() + ": " + cause.getMessage()); 213 } 214 215 216 219 private void missingConfField(String field, String file) throws 220 HttpPresentationException { 221 throw new HttpPresentationException("field \"" + field 222 + 223 "\" not specified in application config file \"" 224 + file + "\""); 225 } 226 227 231 232 private String initConfig(ServletConfig servletConfig) throws 233 ServletException { 234 235 try { 236 String configFileName = servletConfig.getInitParameter( APP_CONFIG_INIT_PARAM_NAME); 238 if (configFileName == null) { 239 throw new HttpPresentationException("init parameter \"" + 240 APP_CONFIG_INIT_PARAM_NAME + 241 "\" not specified for Enhydra servlet"); 242 } 243 String classDefinition = servletConfig.getInitParameter(APP_CONFIG_FILE_CLASS); 246 if (classDefinition == null) 247 classDefinition = EnhydraServer.DEFAULT_CONF_FILE_CLASS; 248 Class imp = null; 249 try { 250 imp = Class.forName(classDefinition); 251 } 252 catch (Exception ex) { 253 try { 254 classDefinition = EnhydraServer.DEFAULT_CONF_FILE_CLASS; 255 imp = Class.forName(classDefinition); 256 } 257 catch (Exception e) { 258 throw new ServletException ("Can not create configFile"); 259 } 260 } 261 262 Class [] classParam = new Class [1]; 263 classParam[0] = Class.forName("java.io.File"); 264 Constructor constr = imp.getConstructor(classParam); 265 Object [] arguments = new Object [1]; 266 File configFile = new File (configFileName); 267 String contextUrl = this.getServletConfig().getServletContext().getRealPath(""); 268 if (!configFile.isAbsolute() && !configFileName.startsWith("/")) { 269 configFile = new File (contextUrl, "WEB-INF/" + configFileName); 270 } 271 arguments[0] = (Object ) (configFile); 272 ConfigFileInterface configF = (ConfigFileInterface) constr.newInstance(arguments); 273 appConfig = configF.getConfig(); 274 275 return configFileName; 276 } 277 catch (Exception except) { 278 throwServletException("Initialization of application failed", except); 279 } 280 return null; 281 } 282 283 288 private void initApplication(ServletConfig servletConfig) throws 289 ServletException { 290 try { 291 int uuu = 0; 292 String configFileName = servletConfig.getInitParameter( APP_CONFIG_INIT_PARAM_NAME); 293 if (configFileName == null) 294 throw new HttpPresentationException("init parameter \"" + 295 APP_CONFIG_INIT_PARAM_NAME + 296 "\" not specified for Enhydra servlet"); 297 String contextUrl = this.getServletConfig().getServletContext(). 298 getRealPath(""); 299 300 File libDir = new File (contextUrl, "WEB-INF/lib"); 302 File [] archives = libDir.listFiles(new ArchiveFilter()); 303 if (archives != null) { 304 for (int i = 0; i < archives.length; i++) { 305 this.appClassLoader.addClassPath(archives[i]); 306 } 307 } 308 309 this.appClassLoader.addClassPath(new File (contextUrl, "WEB-INF/classes")); 311 String [] appClassPath = appConfig.getStrings(APP_CLASS_PATH_FIELD, null); 313 if (appClassPath != null) 314 this.appClassLoader.addClassPath(appClassPath); 315 316 317 String appClass = appConfig.getString(APP_APP_CLASS_FIELD); 319 String name = appClass; 320 338 if (appClass == null) { 339 missingConfField(APP_APP_CLASS_FIELD, configFileName); 340 } 341 presentationPrefix = appConfig.getString(APP_PRESENTATION_PREFIX_FIELD); 342 if (presentationPrefix == null) { 343 missingConfField(APP_PRESENTATION_PREFIX_FIELD, configFileName); 344 } 345 autoReload = appConfig.getBoolean(APP_AUTO_RELOAD_FIELD, false); 346 347 characterEncoding = appConfig.getString(APP_ENCODING_TYPE,null); 348 if (characterEncoding != null) { 349 needToSetCharacterEncoding=true; 350 } 351 352 353 cacheClasses = appConfig.getBoolean("PresentationManager.CacheClasses", true); 355 cacheFiles = appConfig.getBoolean("PresentationManager.CacheFiles", false); 356 357 logChannel.write(Logger.DEBUG, "Loaded Enhydra application: " + appClass); 358 logChannel.write(Logger.DEBUG, " presentation prefix: " + presentationPrefix); 359 360 Class appClassObj = appClassLoader.loadClass(appClass); 362 application = (Application) appClassObj.newInstance(); 363 364 370 Enhydra.register(application); 371 372 try { 373 application.setLogChannel(standardLogger.getChannel(name)); 376 application.setName(name); 378 } 379 finally { 380 Enhydra.unRegister(); 382 } 383 setPresentationManager(context, appClassLoader); 384 385 String [] presTools = appConfig.getStrings(this.APP_PRESENTATION_TOOLS, new String [] {"xmlc"}); 388 for (int i = 0; i < presTools.length; i++) { 389 390 if (presTools[i].equalsIgnoreCase("xmlc")) { 391 boolean xmlcDeferredParsing = appConfig.getBoolean(this.APP_DEFERRED_PARSING_FIELD, false); 393 application.setXMLCFactory(xmlcDeferredParsing); 394 } 395 else if (presTools[i].equalsIgnoreCase("jivan")) { 396 boolean jivanAutoReload = appConfig.getBoolean(this.APP_JIVAN_RELOAD_FIELD, false); 398 application.setJivanFactory(jivanAutoReload); 399 } 400 } 401 403 LogChannel appLogChannel = application.getLogChannel(); 404 if (appLogChannel != null) { 405 if (appLogChannel.isEnabled(XMLC_DOM_STATS_LOG_LEVEL)) { 406 domStatsLogWriter = appLogChannel.getLogWriter(XMLC_DOM_STATS_LOG_LEVEL); 407 } 408 } 409 410 Config mimeTypes = appConfig.getConfig("Server.MimeType"); 413 if (mimeTypes != null) { 414 String extensions[] = mimeTypes.keys(); 415 for (int idx = 0; idx < extensions.length; idx++) { 416 presentationManager.addMimeType(mimeTypes.getString(extensions[idx]), 417 extensions[idx]); 418 } 419 } 420 } 421 catch (Exception except) { 422 throwServletException("Initialization of application failed", except); 423 } 424 } 425 426 434 public synchronized void init(ServletConfig config) throws ServletException { 435 super.init(config); 437 context = config.getServletContext(); 438 initConfig(config); 440 441 442 ClassLoader secondaryLoader = Thread.currentThread().getContextClassLoader(); this.appClassLoader = new MultiClassLoader(secondaryLoader, null, logChannel); appClassLoader.forceSecondaryLoader(true); 446 appClassLoader.enableAutoReloadForSecLoader(this.autoReload); 447 448 try { 449 logClassName = appConfig.getString(EnhydraServer.LOG_CLASS, EnhydraServer.DEFAULT_LOG_CLASS); 450 if (logClassName == null) 451 logClassName = EnhydraServer.DEFAULT_LOG_CLASS; 452 standardLogger = (Logger) Class.forName(logClassName, true, appClassLoader).getConstructor(new 454 Class [] {Boolean.TYPE}).newInstance(new Object [] {new Boolean (true)}); 455 if (needToConfigureLogChannel) { 456 standardLogger.configure(appConfig); 457 needToConfigureLogChannel = false; 458 } 459 } 460 catch (Exception e) { 461 throwServletException("Initialization of logger failed", e); 462 } 463 logChannel = standardLogger.getChannel("Enhydra"); 464 465 initApplication(config); 466 467 ensureAppIsRunning(); 471 475 EnhydraServer es = EnhydraServer.getInstance(); 476 es.register(this); 477 } 478 479 490 private void setPresentationManager(ServletContext context, 491 ClassLoader appClassLoader) throws 492 ServletException { 493 try { 494 presentationManager = new HttpPresentationManager(presentationPrefix, 495 application, appClassLoader, cacheClasses, cacheFiles); 496 presentationManager.setServletAndContext(this, context); 497 } 498 catch (Exception except) { 499 throwServletException("Initialization of presentation manager failed", except); 500 } 501 502 510 Enhydra.register(application); 511 try { 512 application.setHttpPresentationManager(presentationManager); 513 } 514 finally { 515 Enhydra.unRegister(); 517 } 518 } 519 520 523 private synchronized void changeToRunningState() throws ApplicationException { 524 525 boolean isRegistered = (Enhydra.getApplication() != null); 527 if (!isRegistered) { 528 Enhydra.register(application); 529 } 530 try { 531 switch (application.getState()) { 532 case Application.STOPPED: 533 application.startup(appConfig); 534 isRegistered = (Enhydra.getApplication() != null); 535 break; 536 case Application.RUNNING: 537 break; 538 case Application.INCOMPLETE: 539 application.restartup(appConfig); 540 break; 541 case Application.DEAD: 542 throw new ApplicationException("The application " + 543 application.getName() + 544 " is dead"); 545 case Application.HALTED: 546 throw new ApplicationException("The application " + 547 application.getName() + 548 " is halted"); 549 550 default: 551 throw new ApplicationException("The application " + 552 application.getName() + 553 " in invalid state"); 554 } 555 } 556 finally { 557 if (!isRegistered) { 558 Enhydra.unRegister(); 559 } 560 } 561 } 562 563 579 public void serviceDirect(HttpServletRequest req, HttpServletResponse resp) throws 580 ServletException , IOException { 581 582 589 Enhydra.register(application); 590 try { 591 ensureAppIsRunning(); 592 String usrAgent = req.getHeader("user-agent"); 593 String query = req.getQueryString(); 594 boolean wsdl = false; 595 596 if(needToSetCharacterEncoding) 597 req.setCharacterEncoding(characterEncoding); 598 599 600 615 if(query != null && query.equals("wsdl")) 616 { 617 wsdl=true; 618 logChannel.write(Logger.DEBUG, 619 "It is an Axis request for a wsdl sevice description"); 620 } 621 logChannel.write(Logger.DEBUG, "HUA: " + usrAgent, null); 622 623 if (usrAgent != null && (wsdl || axisPattern.matcher(usrAgent).matches())) { 624 logChannel.write(Logger.DEBUG, "It is an Axis request "); 626 if (axisServlet == null) { 627 logChannel.write(Logger.INFO, "Initialising the Axis servlet "+application.getName()); 628 axisServlet = new AxisServlet(); 629 axisServlet.init(getServletConfig()); 630 } 631 try { 632 logChannel.write(Logger.INFO, "Servicing the Axis request "+application.getName()); 634 axisServlet.service(req, resp); 635 } 636 catch (Exception excp) { 637 presentationManager.Run(new ServletHttpPresentationRequest(req), 639 new ServletHttpPresentationResponse(resp, 640 domStatsLogWriter)); 641 } 642 } 643 else 644 645 presentationManager.Run(new ServletHttpPresentationRequest(req), 646 new ServletHttpPresentationResponse(resp, 647 domStatsLogWriter)); 648 } 649 catch (HttpPresentationException except) { 650 throwServletException( 651 "An unhandled error occured while servicing an application request", 652 except); 653 } 654 finally { 655 Enhydra.unRegister(); 657 } 658 } 659 660 666 public void ensureAppIsRunning() throws ServletException { 667 checkAutoReload(); 668 if ( (application != null) && 671 (application.getState() != Application.RUNNING)) { 672 try { 673 changeToRunningState(); 674 context.setAttribute(EnhydraServer.SESSION_MANAGER_KEY, 675 application.getSessionManager()); 676 } 677 catch (Throwable except) { 678 throwServletException("Unable to change application to running state", except); 679 } 680 } 681 } 682 683 686 public String getServletInfo() { 687 return com.lutris.Enhydra.getEnhydraLongName() + "/" + 688 com.lutris.Enhydra.getEnhydraVersion(); } 690 691 703 protected HttpPresentationRequest getHttpPresentationRequest( 704 HttpServletRequest req, 705 HttpServletResponse resp) { 706 return new ServletHttpPresentationRequest(req); 707 } 708 709 721 protected HttpPresentationResponse getHttpPresentationResponse( 722 HttpServletRequest req, 723 HttpServletResponse resp) { 724 return new ServletHttpPresentationResponse(resp, domStatsLogWriter); 725 } 726 727 731 public Application getApplication() { 732 return application; 733 } 734 735 738 protected Config getAppConfigInitParam() { 739 return appConfig; 740 } 741 742 745 protected String getAppConfigInitParamName() { 746 return APP_CONFIG_INIT_PARAM_NAME; 747 } 748 749 761 public void service(HttpServletRequest request, 762 HttpServletResponse response) throws ServletException , 763 IOException { 764 768 if (presentationManager.servletRequestPreprocessor(this, context, 769 request, response)) { 770 return; 772 } 773 774 serviceDirect(request, response); 775 } 776 777 792 public Session getSession(ServletRequest request) { 793 if (application == null) { 794 return null; 795 } 796 Enhydra.register(application); 797 Session s = null; 798 799 try { 800 s = presentationManager.getSession(request); 801 } 802 finally { 803 Enhydra.unRegister(); 804 } 805 return s; 806 } 807 808 817 private void checkAutoReload() throws ServletException { 818 if (autoReload) { 819 if (this.appClassLoader.shouldReload()) { 820 application.shutdown(); 821 822 ClassLoader secondaryLoader = Thread.currentThread().getContextClassLoader(); this.appClassLoader = new MultiClassLoader(secondaryLoader.getParent(), secondaryLoader, logChannel); appClassLoader.forceSecondaryLoader(true); 825 appClassLoader.enableAutoReloadForSecLoader(autoReload); 826 827 initConfig(getServletConfig()); 828 initApplication(getServletConfig()); 829 } 830 } 831 } 832 833 837 public synchronized void destroy() { 838 843 application.shutdown(); 844 EnhydraServer es = EnhydraServer.getInstance(); 846 es.unRegister(this); 847 848 standardLogger = null; 850 logChannel = null; 851 appClassLoader.clearClassPath(); 852 appClassLoader = null; 853 presentationManager = null; 854 } 855 856 } 857 | Popular Tags |