1 29 30 package com.caucho.jsp; 31 32 import com.caucho.jsp.cfg.JspPropertyGroup; 33 import com.caucho.loader.Environment; 34 import com.caucho.log.Log; 35 import com.caucho.server.connection.CauchoResponse; 36 import com.caucho.server.connection.ToCharResponseAdapter; 37 import com.caucho.server.webapp.WebApp; 38 import com.caucho.util.Alarm; 39 import com.caucho.util.Base64; 40 import com.caucho.util.CharBuffer; 41 import com.caucho.util.QDate; 42 import com.caucho.vfs.Depend; 43 import com.caucho.vfs.Dependency; 44 import com.caucho.vfs.Path; 45 import com.caucho.vfs.PersistentDependency; 46 47 import javax.servlet.Servlet ; 48 import javax.servlet.ServletConfig ; 49 import javax.servlet.ServletContext ; 50 import javax.servlet.ServletException ; 51 import javax.servlet.http.HttpServletRequest ; 52 import javax.servlet.http.HttpServletResponse ; 53 import java.io.IOException ; 54 import java.lang.reflect.Method ; 55 import java.util.ArrayList ; 56 import java.util.Enumeration ; 57 import java.util.HashMap ; 58 import java.util.logging.Level ; 59 import java.util.logging.Logger ; 60 61 64 abstract public class Page implements Servlet , ServletConfig , CauchoPage { 65 protected static final Logger _caucho_log = Log.open(Page.class); 66 67 private ServletConfig _config; 68 private WebApp _webApp; 69 70 private ArrayList <PersistentDependency> _depends; 71 private ArrayList <Depend> _cacheDepends; 72 private String _media; 73 protected String _contentType; 74 protected boolean _alwaysModified; 75 protected boolean _neverModified; 76 77 private PageManager.Entry _entry; 78 private long _lastModified; 79 private String _lastModifiedString; 80 private String _etag; 81 private QDate _calendar; 82 83 private long _updateInterval = Environment.getDependencyCheckInterval(); 84 private long _lastUpdateCheck; 85 private JspManager _jspManager; 86 87 private boolean _isRecompiling = false; 88 private int _useCount; 89 private boolean _isDead = true; 90 91 public void init(Path path) 92 throws ServletException 93 { 94 } 95 96 void _caucho_setContentType(String contentType) 97 { 98 _contentType = contentType; 99 } 100 101 void _caucho_setUpdateInterval(long updateInterval) 102 { 103 _updateInterval = updateInterval; 104 } 105 106 void _caucho_setJspManager(JspManager manager) 107 { 108 _jspManager = manager; 109 } 110 111 void _caucho_unload() 112 { 113 if (_jspManager != null) 114 _jspManager.unload(this); 115 } 116 117 void _caucho_setEntry(PageManager.Entry entry) 118 { 119 _entry = entry; 120 } 121 122 protected void _caucho_setContentType(String contentType, String encoding) 123 { 124 if (encoding != null && encoding.equals("ISO-8859-1")) 125 encoding = null; 126 127 _contentType = contentType; 128 } 129 130 133 void _caucho_setUncacheable() 134 { 135 _cacheDepends = null; 136 } 137 138 142 protected void _caucho_setAlwaysModified() 143 { 144 if (_cacheDepends == null) 145 _alwaysModified = true; 146 } 147 148 152 protected void _caucho_setModified() 153 { 154 _alwaysModified = true; 155 } 156 157 161 protected void _caucho_setNeverModified(boolean modified) 162 { 163 _neverModified = modified; 164 } 165 166 171 protected void _caucho_addDepend(Path path) 172 { 173 Depend depend = new Depend(path); 174 depend.setRequireSource(getRequireSource()); 175 176 _caucho_addDepend(depend); 177 } 178 179 184 protected void _caucho_addDepend(PersistentDependency depend) 185 { 186 if (_depends == null) 187 _depends = new ArrayList <PersistentDependency>(); 188 189 if (! _depends.contains(depend)) 190 _depends.add(depend); 191 } 192 193 196 protected void _caucho_addDepend(ArrayList <PersistentDependency> dependList) 197 { 198 if (dependList == null) 199 return; 200 201 for (int i = 0; i < dependList.size(); i++) 202 _caucho_addDepend(dependList.get(i)); 203 } 204 205 213 protected void _caucho_addDepend(Path path, 214 long lastModified, 215 long length) 216 { 217 if (_depends == null) 218 _depends = new ArrayList <PersistentDependency>(); 219 220 Depend depend = new Depend(path, lastModified, length); 221 depend.setRequireSource(getRequireSource()); 222 223 _caucho_addDepend(depend); 224 } 225 226 229 protected void _caucho_setCacheable() 230 { 231 _cacheDepends = new ArrayList <Depend>(); 232 _alwaysModified = false; 233 } 234 235 236 244 protected void _caucho_addCacheDepend(Path path, 245 long lastModified, 246 long length) 247 { 248 if (_cacheDepends == null) 249 _cacheDepends = new ArrayList <Depend>(); 250 251 Depend depend = new Depend(path, lastModified, length); 252 253 if (! _cacheDepends.contains(depend)) 254 _cacheDepends.add(depend); 255 } 256 257 263 void _caucho_setCacheable(ArrayList <Path> depends) 264 { 265 _cacheDepends = new ArrayList <Depend>(); 266 for (int i = 0; i < depends.size(); i++) { 267 Path path = depends.get(i); 268 269 Depend depend = new Depend(path); 270 depend.setRequireSource(getRequireSource()); 271 272 if (! _cacheDepends.contains(depend)) 273 _cacheDepends.add(depend); 274 } 275 } 276 277 280 public boolean _caucho_isModified() 281 { 282 if (_alwaysModified || _isDead) 283 return true; 284 285 if (_depends == null) 286 return false; 287 288 for (int i = 0; i < _depends.size(); i++) { 289 Dependency depend = _depends.get(i); 290 291 if (depend.isModified()) 292 return true; 293 } 294 295 return false; 296 } 297 298 301 public boolean cauchoIsModified() 302 { 303 long now = Alarm.getCurrentTime(); 304 305 if (_alwaysModified || _isDead) 306 return true; 307 else if (now < _lastUpdateCheck + _updateInterval) 308 return false; 309 310 322 323 if (_neverModified) { 324 _lastUpdateCheck = now; 325 326 if (_depends == null) 327 return false; 328 329 for (int i = 0; i < _depends.size(); i++) { 330 Dependency depend = _depends.get(i); 331 if (depend.isModified()) 332 return true; 333 } 334 335 return false; 336 } 337 else { 338 boolean isModified = _caucho_isModified(); 339 340 if (! isModified) 341 _lastUpdateCheck = now; 342 return isModified; 343 } 344 } 345 346 protected HashMap <String ,Method > _caucho_getFunctionMap() 347 { 348 return null; 349 } 350 351 354 private boolean getRequireSource() 355 { 356 return false; 357 } 358 359 362 public void init(ServletConfig config) 363 throws ServletException 364 { 365 if (_config != null) 366 return; 367 368 _config = config; 369 _isDead = false; 370 371 _webApp = (WebApp) config.getServletContext(); 372 373 cauchoIsModified(); 374 375 if (! disableLog() && _caucho_log.isLoggable(Level.FINE)) 376 _caucho_log.fine(getClass().getName() + " init"); 377 } 378 379 382 public boolean isInit() 383 { 384 return _config != null; 385 } 386 387 390 public WebApp _caucho_getApplication() 391 { 392 return _webApp; 393 } 394 395 public ServletContext getServletContext() 396 { 397 return _webApp; 398 } 399 400 public String getServletName() 401 { 402 return _config.getServletName(); 403 } 404 405 public String getInitParameter(String name) 406 { 407 return _config.getInitParameter(name); 408 } 409 410 public Enumeration getInitParameterNames() 411 { 412 return _config.getInitParameterNames(); 413 } 414 415 public void log(String msg) 416 { 417 _webApp.log(getClass().getName() + ": " + msg); 418 } 419 420 public void log(String msg, Throwable cause) 421 { 422 _webApp.log(getClass().getName() + ": " + msg, cause); 423 } 424 425 public String getServletInfo() 426 { 427 return "A JSP Page"; 428 } 429 430 boolean disableLog() 431 { 432 JspPropertyGroup jsp = _webApp.getJsp(); 433 434 if (jsp != null) 435 return jsp.isDisableLog(); 436 437 return true; 438 } 439 440 443 public ServletConfig getServletConfig() 444 { 445 return _config; 446 } 447 448 451 public void _caucho_init(HttpServletRequest req, HttpServletResponse res) 452 { 453 if (_contentType != null) 454 res.setContentType(_contentType); 455 else 456 res.setContentType("text/html"); 457 } 458 459 465 public long getLastModified(HttpServletRequest request) 466 { 467 return _caucho_lastModified(); 468 } 469 470 474 public long _caucho_lastModified() 475 { 476 if (_cacheDepends == null) { 477 return 0; 478 } 479 else { 480 return calculateLastModified(_depends, _cacheDepends); 481 } 482 } 483 484 494 public static long calculateLastModified(ArrayList <PersistentDependency> depends, 495 ArrayList <Depend> cacheDepends) 496 { 497 long lastModified = 0; 498 499 for (int i = 0; i < depends.size(); i++) { 500 PersistentDependency dependency = depends.get(i); 501 502 if (dependency instanceof Depend) { 503 Depend depend = (Depend) dependency; 504 long modified = depend.getLastModified(); 505 if (lastModified < modified) 506 lastModified = modified; 507 } 508 } 509 510 for (int i = 0; cacheDepends != null && i < cacheDepends.size(); i++) { 511 Depend depend = cacheDepends.get(i); 512 long modified = depend.getLastModified(); 513 if (lastModified < modified) 514 lastModified = modified; 515 } 516 517 return lastModified; 518 } 519 520 530 public void pageservice(HttpServletRequest req, HttpServletResponse res) 531 throws IOException , ServletException 532 { 533 PageManager.Entry entry = _entry; 534 if (entry != null) 535 entry.accessPage(); 536 537 long lastModified = getLastModified(req); 538 539 if (lastModified > 0) { 540 if (_calendar == null) 541 _calendar = new QDate(); 542 543 String etag = _etag; 544 if (lastModified != _lastModified) { 545 CharBuffer cb = new CharBuffer(); 546 cb.append('"'); 547 Base64.encode(cb, lastModified); 548 cb.append('"'); 549 etag = cb.close(); 550 _etag = etag; 551 552 synchronized (_calendar) { 553 _calendar.setGMTTime(lastModified); 554 _lastModifiedString = _calendar.printDate(); 555 } 556 557 _lastModified = lastModified; 558 } 559 560 String ifMatch = req.getHeader("If-None-Match"); 561 if (etag.equals(ifMatch)) { 562 res.sendError(res.SC_NOT_MODIFIED); 563 return; 564 } 565 566 String ifModifiedSince = req.getHeader("If-Modified-Since"); 567 if (_lastModifiedString.equals(ifModifiedSince)) { 568 res.sendError(res.SC_NOT_MODIFIED); 569 return; 570 } 571 572 res.setHeader("ETag", etag); 573 res.setHeader("Last-Modified", _lastModifiedString); 574 } 575 576 if (res instanceof CauchoResponse) { 577 service(req, res); 578 } 579 else { 580 ToCharResponseAdapter resAdapt = ToCharResponseAdapter.create(res); 582 585 try { 586 service(req, resAdapt); 587 } finally { 588 resAdapt.close(); 589 ToCharResponseAdapter.free(resAdapt); 590 } 591 } 592 } 593 594 protected void setDead() 595 { 596 _isDead = true; 597 } 598 599 public boolean isDead() 600 { 601 return _isDead; 602 } 603 604 608 public boolean startRecompiling() 609 { 610 boolean allowRecompiling; 611 612 synchronized (this) { 613 allowRecompiling = _isDead || ! _isRecompiling; 614 _isRecompiling = true; 615 } 616 617 return allowRecompiling; 618 } 619 620 String getErrorPage() { return null; } 621 622 625 public void _caucho_use() 626 { 627 synchronized (this) { 628 _useCount++; 629 } 630 } 631 632 635 public void _caucho_free() 636 { 637 synchronized (this) { 638 _useCount--; 639 } 640 641 if (_useCount <= 0) 642 destroy(); 643 } 644 645 public void destroy() 646 { 647 if (_isDead) 648 return; 649 650 _isDead = true; 651 655 656 _entry = null; 657 658 Thread thread = Thread.currentThread(); 659 ClassLoader oldLoader = thread.getContextClassLoader(); 660 try { 661 thread.setContextClassLoader(getClass().getClassLoader()); 662 663 _caucho_log.fine(getClass().getName() + " destroy"); 664 } finally { 665 thread.setContextClassLoader(oldLoader); 666 } 667 } 668 } 669 | Popular Tags |