1 52 53 package com.go.teaservlet; 54 55 import java.io.BufferedReader ; 56 import java.io.File ; 57 import java.io.IOException ; 58 import java.util.Collection ; 59 import java.util.Iterator ; 60 import java.util.Map ; 61 import java.util.HashMap ; 62 import java.util.TreeSet ; 63 import java.util.Arrays ; 64 import java.util.ArrayList ; 65 import java.util.Vector ; 66 67 import javax.servlet.ServletContext ; 68 import javax.servlet.http.HttpServletRequest ; 69 70 import com.go.trove.log.Log; 71 import com.go.trove.util.ClassInjector; 72 import com.go.trove.io.LinePositionReader; 73 74 import com.go.tea.compiler.CompilationUnit; 75 import com.go.tea.compiler.ErrorEvent; 76 import com.go.tea.compiler.ErrorListener; 77 import com.go.tea.compiler.SourceInfo; 78 import com.go.tea.runtime.TemplateLoader; 79 import com.go.tea.util.AbstractFileCompiler; 80 import com.go.tea.util.FileCompiler; 81 import com.go.teaservlet.util.RemoteCompiler; 82 83 93 class TemplateDepot { 94 95 public final static String TEMPLATE_PACKAGE = "com.go.teaservlet.template"; 96 97 98 public final static String SYSTEM_PACKAGE = "system"; 99 100 101 public final static String SYSTEM_TEMPLATE_PACKAGE = TEMPLATE_PACKAGE + '.' + SYSTEM_PACKAGE; 102 103 private Log mLog; 104 105 private Class mContextClass; 106 107 private ClassLoader mParentLoader; 108 109 private String mDefaultTemplate; 110 111 112 private File mDestinationDir; 113 114 115 private String mEncoding; 116 117 private boolean mExceptionGuardian; 118 119 private boolean mPreloadTemplates; 120 121 122 private TemplateLoader mLoader; 123 124 125 private boolean mRejectErrors = false; 126 127 private final Object mLoadLock = new Object (); 128 129 139 TemplateDepot(Log log, Class contextClass, 140 String defaultTemplate, File destDir, String encoding, 141 boolean exceptionGuardian,boolean preloadTemplates) { 142 mLog = log; 143 mContextClass = contextClass; 144 mParentLoader = contextClass.getClassLoader(); 145 mDefaultTemplate = defaultTemplate; 146 mDestinationDir = destDir; 147 mEncoding = encoding; 148 mExceptionGuardian = exceptionGuardian; 149 mPreloadTemplates = preloadTemplates; 150 } 151 152 public boolean isExceptionGuardianEnabled() { 153 return mExceptionGuardian; 154 } 155 156 168 public TemplateLoader.Template findTemplate(String uri, 169 HttpServletRequest request, 170 ApplicationResponse response) 171 throws NoSuchMethodException , IOException , LinkageError 172 { 173 TemplateLoader loader = getTemplateLoader(); 174 TemplateLoader.Template template = null; 175 176 boolean useDefault = uri.endsWith("/"); 179 180 while (uri.startsWith("/")) { 182 uri = uri.substring(1); 183 } 184 while (uri.endsWith("/")) { 185 uri = uri.substring(0, uri.length() - 1); 186 } 187 String name = uri.replace('/', '.'); 188 189 if (!useDefault) { 191 try { 193 template = loader.getTemplate(name); 194 } 195 catch (ClassNotFoundException e) { 196 mLog.debug("Can't find template \"" + name + "\": " + e); 197 template = null; 198 } 199 } 200 201 if ((template == null) && (mDefaultTemplate != null)) { 203 if (name.length() == 0) { 204 name = mDefaultTemplate; 205 } 206 else { 207 name = name + '.' + mDefaultTemplate; 208 } 209 210 try { 211 template = loader.getTemplate(name); 212 213 if (template != null && !useDefault) { 215 StringBuffer location = new StringBuffer (request.getRequestURI()); 216 int length = location.length(); 217 if (length == 0 || location.charAt(length - 1) != '/') { 218 location.append('/'); 219 } 220 String query = request.getQueryString(); 221 if (query != null) { 222 location.append('?').append(query); 223 } 224 response.setStatus(response.SC_MOVED_PERMANENTLY); 225 response.sendRedirect(location.toString()); 226 } 227 } 228 catch (ClassNotFoundException e) { 229 mLog.debug("Can't find default template \"" + 230 name + "\": " + e); 231 } 232 } 233 234 return template; 235 } 236 237 247 public TemplateLoadResult loadTemplates(String directory) { 248 return loadTemplates(new String []{directory}, false); 249 } 250 251 261 public TemplateLoadResult loadTemplates(String [] directories) { 262 return loadTemplates(directories, false); 263 } 264 265 277 public TemplateLoadResult loadTemplates(String directory, boolean force) { 278 return loadTemplates(new String []{directory}, force); 279 } 280 281 293 public TemplateLoadResult loadTemplates(String [] directories, 294 boolean force) { 295 synchronized (mLoadLock) { 297 return loadTemplates0(directories, force); 298 } 299 } 300 301 private TemplateLoadResult loadTemplates0(String [] directories, 302 boolean force) { 303 if (directories.length == 0) { 304 setTemplateLoader(null); 305 mRejectErrors = false; 306 return new TemplateLoadResult(); 307 } 308 Vector remoteVec = new Vector (); 309 Vector localVec = new Vector (); 310 311 for (int i=0; i<directories.length; i++) { 313 if (directories[i].startsWith("http://")) { 314 remoteVec.add(directories[i]); 315 } 316 else { 317 localVec.add(new File (directories[i])); 318 } 319 } 320 File [] localDirs = (File [])localVec.toArray(new File [localVec.size()]); 321 String [] remoteDirs = (String [])remoteVec.toArray 322 (new String [remoteVec.size()]); 323 324 ClassInjector injector = new ClassInjector 325 (mParentLoader, mDestinationDir, TEMPLATE_PACKAGE); 326 ClassInjector mainLine = null; 327 if (mPreloadTemplates) { 328 mainLine = injector; 329 } 330 331 FileCompiler lCompiler = new FileCompiler(localDirs, 334 TEMPLATE_PACKAGE, 335 mDestinationDir, 336 mainLine, 337 mEncoding); 338 339 RemoteCompiler rCompiler = new RemoteCompiler(remoteDirs, 340 TEMPLATE_PACKAGE, 341 mDestinationDir, 342 mainLine, 343 mEncoding); 344 345 lCompiler.setForceCompile(force); 346 rCompiler.setForceCompile(force); 347 348 TemplateLoadResult result = compileTemplates("local", lCompiler); 349 TemplateLoadResult remoteResult = compileTemplates("remote",rCompiler); 350 result.mergeResults(remoteResult); 351 352 if (mRejectErrors && !result.isSuccessful()) { 353 injector = null; 354 mLog.warn("Templates not reloaded"); 355 return result; 356 } 357 358 TemplateLoader loader = 359 new TemplateAdapter(mContextClass, injector, TEMPLATE_PACKAGE); 360 setTemplateLoader(loader); 361 362 String [] lNames, rNames; 363 try { 364 lNames = lCompiler.getAllTemplateNames(); 365 } 366 catch (IOException e) { 367 mLog.warn(e); 368 lNames = new String [0]; 369 } 370 371 rNames = rCompiler.getAllTemplateNames(); 372 373 String [] allNames = new String [lNames.length + rNames.length]; 374 System.arraycopy(lNames, 0, allNames, 0, lNames.length); 375 System.arraycopy(rNames, 0, allNames, lNames.length, rNames.length); 376 377 boolean recompile = false; 378 if (mPreloadTemplates) { 379 for (int i=0; i<allNames.length; i++) { 380 try { 381 loader.getTemplate(allNames[i]); 382 } 383 catch (ClassNotFoundException e) { 384 mLog.debug(e.toString()); 385 } 386 catch (NoSuchMethodException e) { 387 if (!force) { 388 mLog.debug(e.toString()); 389 recompile = true; 390 break; 391 } 392 else { 393 mLog.warn(e); 394 } 395 } 396 catch (LinkageError e) { 397 if (!force) { 398 mLog.debug(e.toString()); 399 recompile = true; 400 break; 401 } 402 else { 403 mLog.warn(e); 404 } 405 } 406 } 407 } 408 409 if (recompile) { 411 mLog.info("Re-compiling all templates"); 412 result = loadTemplates(directories, true); 413 } 414 415 if (result.isSuccessful()) { 419 mRejectErrors = true; 420 } 421 422 return result; 423 } 424 425 public synchronized TemplateLoader.Template[] getLoadedTemplates() { 426 return getTemplateLoader().getLoadedTemplates(); 427 } 428 429 public synchronized TemplateLoader getTemplateLoader() { 430 if (mLoader == null) { 431 mLoader = new TemplateAdapter(mContextClass, 432 new ClassInjector(mParentLoader), 433 TEMPLATE_PACKAGE); 434 } 435 return mLoader; 436 } 437 438 private synchronized void setTemplateLoader(TemplateLoader loader) { 439 mLoader = loader; 440 } 441 442 447 private TemplateLoadResult compileTemplates(String templateTypes, 448 AbstractFileCompiler compiler) { 449 compiler.setRuntimeContext(mContextClass); 450 compiler.setClassLoader(mParentLoader); 451 compiler.setExceptionGuardianEnabled(mExceptionGuardian); 452 453 ErrorRetriever retriever = new ErrorRetriever(); 454 compiler.addErrorListener(retriever); 455 456 mLog.info("Compiling " + templateTypes + " templates..."); 458 459 String [] templateNames = null; 460 TemplateError[] compileErrors = null; 461 boolean successfulReload = true; 462 463 try { 464 templateNames = compiler.compileAll(); 465 } 466 catch (Exception e) { 467 successfulReload = false; 468 mLog.error("Error compiling " + templateTypes + " templates"); 469 mLog.error(e); 470 } 471 finally { 472 compileErrors = retriever.getTemplateErrors(); 473 retriever.finalize(); 474 } 475 476 if (templateNames != null && templateNames.length > 0) { 477 for (int i = 0; i < templateNames.length; i++) { 478 mLog.info(templateNames[i]); 479 } 480 } 481 482 int errors = compiler.getErrorCount(); 484 if (errors > 0) { 485 successfulReload = false; 486 if (errors == 1) { 487 mLog.warn(errors + " error compiling " + 488 templateTypes + " templates"); 489 } 490 else { 491 mLog.warn(errors + " errors compiling " + 492 templateTypes + " templates"); 493 } 494 } 495 else { 496 if (templateNames == null || templateNames.length == 0) { 497 mLog.info("No templates needed to be compiled"); 498 } 499 else { 500 mLog.info("Templates compiled successfully"); 501 } 502 } 503 504 java.util.Arrays.sort(templateNames, String.CASE_INSENSITIVE_ORDER); 505 506 return new TemplateLoadResult 507 (templateNames, compileErrors, successfulReload); 508 } 509 510 public static class TemplateLoadResult { 511 private boolean mSuccess; 512 private String [] mReloaded; 513 private TemplateError[] mErrors; 514 515 public TemplateLoadResult() { 516 this(new String [0], new TemplateError[0], true); 517 } 518 519 public TemplateLoadResult(String [] recompiledTemplates, 520 TemplateError[] errorList, 521 boolean successfulReload) { 522 mSuccess = successfulReload; 523 mErrors = errorList; 524 mReloaded = recompiledTemplates; 525 } 526 527 public void mergeResults(TemplateLoadResult result) { 528 mSuccess = mSuccess && result.isSuccessful(); 529 530 TemplateError[] combinedErrors = new TemplateError 531 [mErrors.length + result.getTemplateLoadErrors().length]; 532 System.arraycopy(mErrors,0,combinedErrors,0,mErrors.length); 533 System.arraycopy(result.getTemplateLoadErrors(), 534 0,combinedErrors,mErrors.length, 535 result.getTemplateLoadErrors().length); 536 mErrors = combinedErrors; 537 538 String [] combinedReloads = new String 539 [mReloaded.length + result.getReloadedTemplates().length]; 540 System.arraycopy(mReloaded,0,combinedReloads,0,mReloaded.length); 541 System.arraycopy(result.getReloadedTemplates(), 542 0,combinedReloads,mReloaded.length, 543 result.getReloadedTemplates().length); 544 mReloaded = combinedReloads; 545 } 546 547 public boolean isSuccessful() { 548 return mSuccess; 549 } 550 551 public String [] getReloadedTemplates() { 552 return mReloaded; 553 } 554 555 public TemplateError[] getTemplateLoadErrors() { 556 return mErrors; 557 } 558 } 559 560 private class ErrorRetriever implements ErrorListener { 561 private Collection mTemplateErrors = new ArrayList (); 562 563 564 private LinePositionReader mOpenReader; 565 566 private CompilationUnit mOpenUnit; 567 568 public TemplateError[] getTemplateErrors() { 569 return (TemplateError[])mTemplateErrors.toArray 570 (new TemplateError[mTemplateErrors.size()]); 571 } 572 573 577 public void compileError(ErrorEvent event) { 578 mLog.warn("Error in " + event.getDetailedErrorMessage()); 579 580 SourceInfo info = event.getSourceInfo(); 581 if (info == null) { 582 mTemplateErrors.add(new TemplateError(event, "", 0, 0, 0)); 583 return; 584 } 585 586 CompilationUnit unit = event.getCompilationUnit(); 587 if (unit == null) { 588 mTemplateErrors.add(new TemplateError(event, "", 0, 0, 0)); 589 return; 590 } 591 592 int line = info.getLine(); 593 int errorStartPos = info.getStartPosition(); 594 int errorEndPos = info.getEndPosition(); 595 int detailPos = info.getDetailPosition(); 596 597 try { 598 if (mOpenReader == null || 599 mOpenUnit != unit || 600 mOpenReader.getLineNumber() >= line) { 601 602 if (mOpenReader != null) { 603 mOpenReader.close(); 604 } 605 mOpenUnit = unit; 606 mOpenReader = new LinePositionReader 607 (new BufferedReader (unit.getReader())); 608 } 609 610 mOpenReader.skipForwardToLine(line); 611 int linePos = mOpenReader.getNextPosition(); 612 613 String lineStr = mOpenReader.readLine(); 614 lineStr = mOpenReader.cleanWhitespace(lineStr); 615 616 TemplateError te = new TemplateError 617 (event, lineStr, 618 errorStartPos - linePos, 619 detailPos - linePos, 620 errorEndPos - linePos); 621 622 mTemplateErrors.add(te); 623 } 624 catch (IOException ex) { 625 mTemplateErrors.add(new TemplateError(event, "", 0, 0, 0)); 626 mLog.error(ex); 627 } 628 } 629 630 public void finalize() { 631 if (mOpenReader != null) { 633 try { 634 mOpenReader.close(); 635 } 636 catch (IOException e) { 637 mLog.error(e); 638 } 639 } 640 mOpenReader = null; 641 mOpenUnit = null; 642 } 643 } 644 } 645 | Popular Tags |