1 29 30 package com.caucho.jsp; 31 32 import com.caucho.config.Config; 33 import com.caucho.config.ConfigException; 34 import com.caucho.config.types.FileSetType; 35 import com.caucho.jsp.cfg.JspPropertyGroup; 36 import com.caucho.jsp.cfg.TldPreload; 37 import com.caucho.jsp.cfg.TldTaglib; 38 import com.caucho.loader.DynamicClassLoader; 39 import com.caucho.loader.EnvironmentLocal; 40 import com.caucho.log.Log; 41 import com.caucho.server.util.CauchoSystem; 42 import com.caucho.server.webapp.WebApp; 43 import com.caucho.util.Alarm; 44 import com.caucho.util.L10N; 45 import com.caucho.vfs.JarPath; 46 import com.caucho.vfs.MergePath; 47 import com.caucho.vfs.Path; 48 import com.caucho.vfs.ReadStream; 49 import com.caucho.vfs.Vfs; 50 51 import java.io.IOException ; 52 import java.io.InputStream ; 53 import java.lang.ref.SoftReference ; 54 import java.util.ArrayList ; 55 import java.util.Enumeration ; 56 import java.util.HashMap ; 57 import java.util.jar.JarFile ; 58 import java.util.logging.Level ; 59 import java.util.logging.Logger ; 60 import java.util.zip.ZipEntry ; 61 import java.util.zip.ZipFile ; 62 63 66 public class TldManager { 67 static final L10N L = new L10N(TldManager.class); 68 private static final Logger log = Log.open(TldManager.class); 69 70 private static ArrayList <TldPreload> _cauchoTaglibs; 71 private static ArrayList <TldPreload> _globalTaglibs; 72 private static ArrayList <Path> _globalPaths; 73 74 private static EnvironmentLocal<TldManager> _localManager 75 = new EnvironmentLocal<TldManager>(); 76 77 private JspResourceManager _resourceManager; 78 private WebApp _webApp; 79 80 private HashMap <Path,SoftReference <TldTaglib>> _tldMap 81 = new HashMap <Path,SoftReference <TldTaglib>>(); 82 83 private JspParseException _loadAllTldException; 84 private String _tldDir; 85 private FileSetType _tldFileSet; 86 87 private volatile boolean _isInit; 88 89 private Config _config = new Config(); 90 private ArrayList <TldPreload> _preloadTaglibs; 91 92 private TldManager(JspResourceManager resourceManager, 93 WebApp app) 94 throws JspParseException, IOException 95 { 96 _resourceManager = resourceManager; 97 _webApp = app; 98 99 if (app != null) { 100 JspPropertyGroup jsp = app.getJsp(); 101 if (jsp != null) 102 _tldFileSet = jsp.getTldFileSet(); 103 } 104 105 initGlobal(); 108 } 109 110 static TldManager create(JspResourceManager resourceManager, 111 WebApp app) 112 throws JspParseException, IOException 113 { 114 115 TldManager manager = null; 116 117 synchronized (_localManager) { 118 manager = _localManager.getLevel(); 119 120 if (manager != null) 121 return manager; 122 123 manager = new TldManager(resourceManager, app); 124 _localManager.set(manager); 125 } 126 127 return manager; 128 } 129 130 133 void setWebApp(WebApp webApp) 134 { 135 _webApp = webApp; 136 } 137 138 public String getSchema() 139 { 140 return "com/caucho/jsp/cfg/jsp-tld.rnc"; 141 } 142 143 public void setTldDir(String tldDir) 144 { 145 _tldDir = tldDir; 146 } 147 148 public void setTldFileSet(FileSetType tldFileSet) 149 { 150 _tldFileSet = tldFileSet; 151 } 152 153 157 public synchronized void init() 158 throws JspParseException, IOException 159 { 160 if (_isInit) 161 return; 162 _isInit = true; 163 164 log.fine("Loading .tld files"); 165 166 String dir; 167 168 if (_tldDir == null) 169 dir = "WEB-INF"; 170 else if (_tldDir.startsWith("/")) 171 dir = _tldDir.substring(1); 172 else if (_tldDir.startsWith("WEB-INF")) 173 dir = _tldDir; 174 else 175 dir = "WEB-INF/" + _tldDir; 176 177 FileSetType fileSet = _tldFileSet; 178 if (fileSet == null) { 179 fileSet = new FileSetType(); 180 fileSet.setDir(_resourceManager.resolvePath(dir)); 181 try { 182 fileSet.init(); 183 } catch (Exception e) { 184 log.config(e.toString()); 185 } 186 } 187 188 ArrayList <TldPreload> taglibs = new ArrayList <TldPreload>(); 189 190 taglibs.addAll(_globalTaglibs); 191 192 MergePath classPath = new MergePath(); 193 classPath.addClassPath(); 194 195 ArrayList <Path> paths = classPath.getMergePaths(); 196 197 for (int i = 0; i < paths.size(); i++) { 198 Path subPath = paths.get(i); 199 200 if (_globalPaths.contains(subPath)) 201 continue; 202 203 if (subPath instanceof JarPath) 204 loadJarTlds(taglibs, (JarPath) subPath, "META-INF"); 205 else 206 loadAllTlds(taglibs, subPath.lookup("META-INF"), 64, "META-INF"); 207 } 208 209 if (fileSet != null) 210 loadAllTlds(taglibs, fileSet); 211 212 222 taglibs.addAll(_cauchoTaglibs); 223 224 _preloadTaglibs = taglibs; 225 226 for (int i = 0; i < taglibs.size(); i++) { 227 try { 228 taglibs.get(i).initListeners(_webApp); 229 } catch (Exception e) { 230 throw new JspParseException(e); 231 } 232 } 233 } 234 235 public synchronized void initGlobal() 236 { 237 if (_globalTaglibs == null) { 240 if (! Alarm.isTest()) { 241 log.info("Loading .tld files from global classpath"); 242 } 243 244 ArrayList <TldPreload> globalTaglibs = new ArrayList <TldPreload>(); 245 ArrayList <TldPreload> cauchoTaglibs = new ArrayList <TldPreload>(); 246 247 Thread thread = Thread.currentThread(); 248 ClassLoader oldLoader = thread.getContextClassLoader(); 249 thread.setContextClassLoader(TldManager.class.getClassLoader()); 250 try { 251 MergePath globalClassPath = new MergePath(); 252 globalClassPath.addClassPath(); 253 254 ArrayList <Path> paths = globalClassPath.getMergePaths(); 255 _globalPaths = paths; 256 257 loadClassPathTlds(globalTaglibs, paths, ""); 258 259 for (int i = globalTaglibs.size() - 1; i >= 0; i--) { 260 TldPreload tld = globalTaglibs.get(i); 261 262 if (tld.getPath() == null || tld.getPath().getPath() == null) 263 continue; 264 265 String tldPathName = tld.getPath().getPath(); 266 267 if (tldPathName.startsWith("/com/caucho")) { 268 cauchoTaglibs.add(globalTaglibs.remove(i)); 269 } 270 } 271 } catch (Exception e) { 272 log.log(Level.WARNING, e.toString(), e); 273 } finally { 274 thread.setContextClassLoader(oldLoader); 275 } 276 277 _globalTaglibs = globalTaglibs; 278 _cauchoTaglibs = cauchoTaglibs; 279 } 280 } 281 282 private void loadClassPathTlds(ArrayList <TldPreload> taglibs, 283 ArrayList <Path> paths, 284 String prefix) 285 throws JspParseException, IOException 286 { 287 for (int i = 0; i < paths.size(); i++) { 288 Path subPath = paths.get(i); 289 290 if (subPath instanceof JarPath) 291 loadJarTlds(taglibs, (JarPath) subPath, prefix); 292 else if (prefix != null && ! prefix.equals("")) 293 loadAllTlds(taglibs, subPath.lookup(prefix), 64, prefix); 294 else 295 loadAllTlds(taglibs, subPath.lookup("META-INF"), 64, "META-INF"); 296 } 297 } 298 299 305 306 private void loadAllTlds(ArrayList <TldPreload> taglibs, 307 FileSetType fileSet) 308 throws JspParseException, IOException 309 { 310 for (Path path : fileSet.getPaths()) { 311 if (path.getPath().startsWith(".")) { 312 } 313 else if (path.getPath().endsWith(".tld") && 314 path.isFile() && path.canRead()) { 315 try { 316 TldPreload taglib = parseTldPreload(path); 317 318 taglibs.add(taglib); 319 320 if (taglib.getURI() == null && 321 taglib.getConfigException() != null && 322 _loadAllTldException == null) 323 _loadAllTldException = new JspLineParseException(taglib.getConfigException()); 324 } catch (Throwable e) { 325 log.warning(e.getMessage()); 326 } 327 } 328 } 329 } 330 331 private void loadAllTlds(ArrayList <TldPreload> taglibs, 332 Path path, int depth, String userPath) 333 throws JspParseException, IOException 334 { 335 if (depth < 0) 336 throw new JspParseException(L.l("max depth exceeded while reading .tld files. Probable loop in filesystem detected at `{0}'.", path)); 337 338 path.setUserPath(userPath); 339 340 if (path.getPath().startsWith(".")) { 341 } 342 else if (path.getPath().endsWith(".tld") && 343 path.isFile() && path.canRead()) { 344 try { 345 TldPreload taglib = parseTldPreload(path); 346 347 taglibs.add(taglib); 348 349 if (taglib.getURI() == null && 350 taglib.getConfigException() != null && 351 _loadAllTldException == null) 352 _loadAllTldException = new JspLineParseException(taglib.getConfigException()); 353 } catch (Throwable e) { 354 362 363 log.warning(e.getMessage()); 364 } 365 } 366 else if (path.isDirectory()) { 367 String []fileNames = path.list(); 368 369 for (int i = 0; fileNames != null && i < fileNames.length; i++) { 370 String name = fileNames[i]; 371 372 ArrayList <Path> resources = path.getResources(name); 373 374 for (int j = 0; resources != null && j < resources.size(); j++) { 375 Path subpath = resources.get(j); 376 377 loadAllTlds(taglibs, subpath, depth - 1, userPath + "/" + name); 378 } 379 } 380 } 381 } 382 383 private void loadJarTlds(ArrayList <TldPreload> taglibs, 384 JarPath jar, 385 String prefix) 386 throws JspParseException, IOException 387 { 388 if (! jar.getContainer().canRead()) 389 return; 390 391 String nativePath = jar.getContainer().getNativePath(); 392 ZipFile zipFile; 393 394 if (nativePath.endsWith(".jar")) 395 zipFile = new JarFile (nativePath); 396 else 397 zipFile = new ZipFile (nativePath); 398 399 try { 400 Enumeration <? extends ZipEntry > en = zipFile.entries(); 401 while (en.hasMoreElements()) { 402 ZipEntry entry = en.nextElement(); 403 String name = entry.getName(); 404 405 if (name.startsWith(prefix) && name.endsWith(".tld")) { 406 Path path = jar.lookup(name); 407 408 try { 409 TldPreload taglib = parseTldPreload(path); 410 411 taglibs.add(taglib); 412 413 if (taglib.getURI() == null && 414 taglib.getConfigException() != null && 415 _loadAllTldException == null) 416 _loadAllTldException = new JspLineParseException(taglib.getConfigException()); 417 } catch (Throwable e) { 418 426 427 log.warning(e.getMessage()); 428 } 429 } 430 } 431 } finally { 432 zipFile.close(); 433 } 434 } 435 436 439 TldTaglib parseTld(String uri, String mapLocation, String location) 440 throws JspParseException, IOException 441 { 442 init(); 443 444 for (int i = 0; i < _preloadTaglibs.size(); i++) { 445 TldPreload preload = _preloadTaglibs.get(i); 446 447 if (uri.equals(preload.getURI()) 448 && (mapLocation == null 449 || mapLocation.equals(preload.getLocation()) 450 || mapLocation.equals(uri))) { 451 return parseTld(preload.getPath()); 452 } 453 } 454 455 return parseTld(location); 456 } 457 458 461 TldTaglib parseTld(String location) 462 throws JspParseException, IOException 463 { 464 init(); 465 466 TldTaglib tld = findTld(location); 467 468 477 478 return tld; 479 } 480 481 484 private TldTaglib findTld(String location) 485 throws JspParseException, IOException 486 { 487 InputStream is = null; 488 489 Path path; 490 491 if (location.startsWith("file:")) { 492 path = _resourceManager.resolvePath(location); 493 } 494 else if (location.indexOf(':') >= 0 && ! location.startsWith("file:") && 495 location.indexOf(':') < location.indexOf('/')) { 496 if (_loadAllTldException != null) 497 throw _loadAllTldException; 498 499 return null; 500 504 } 505 else if (! location.startsWith("/")) 506 path = _resourceManager.resolvePath("WEB-INF/" + location); 507 else 508 path = _resourceManager.resolvePath("." + location); 509 510 path.setUserPath(location); 511 512 Path jar = null; 513 514 if (location.endsWith(".jar")) { 515 path = findJar(location); 516 517 if (path != null && path.exists()) { 518 jar = JarPath.create(path); 519 if (jar.lookup("META-INF/taglib.tld").exists()) 520 return parseTld(jar.lookup("META-INF/taglib.tld")); 521 else if (jar.lookup("meta-inf/taglib.tld").exists()) 522 return parseTld(jar.lookup("meta-inf/taglib.tld")); 523 else 524 throw new JspParseException(L.l("can't find META-INF/taglib.tld in `{0}'", 525 location)); 526 } 527 else { 528 throw new JspParseException(L.l("Can't find taglib `{0}'. A taglib uri ending in *.jar must point to an actual jar or match a URI in a .tld file.", location)); 529 } 530 } 531 else if (path.exists() && path.canRead() && path.isFile()) 532 return parseTld(path); 533 534 if (_loadAllTldException != null) 535 throw _loadAllTldException; 536 else 537 throw new JspParseException(L.l("Can't find taglib-location `{0}'. The taglib-location must match a tag library either:\n1) by pointing to a .tld directly, relative to the application's root directory\n2) specified in the web.xml\n3) defined in a jar's .tld in META-INF\n4) defined in a .tld in WEB-INF\n5) predefined by Resin", 538 location)); 539 } 540 541 546 private TldTaglib parseTld(Path path) 547 throws JspParseException, IOException 548 { 549 SoftReference <TldTaglib> taglibRef = _tldMap.get(path); 550 TldTaglib taglib; 551 552 if (taglibRef != null) { 553 taglib = taglibRef.get(); 554 555 if (taglib != null && ! taglib.isModified()) 556 return taglib; 557 } 558 559 ReadStream is = path.openRead(); 560 561 try { 562 taglib = parseTld(is); 563 564 if (path instanceof JarPath) 565 taglib.setJarPath(path.lookup("/")); 566 567 _tldMap.put(path, new SoftReference <TldTaglib>(taglib)); 568 569 return taglib; 570 } finally { 571 is.close(); 572 } 573 } 574 575 580 private TldTaglib parseTld(InputStream is) 581 throws JspParseException, IOException 582 { 583 TldTaglib taglib = new TldTaglib(); 584 585 if (is instanceof ReadStream) { 586 Path path = ((ReadStream) is).getPath(); 587 588 path.setUserPath(path.getURL()); 589 } 590 591 String schema = null; 592 593 if (_webApp.getJsp() == null || 594 _webApp.getJsp().isValidateTaglibSchema()) { 595 schema = getSchema(); 596 } 597 598 try { 599 Config config = new Config(); 600 config.setEL(false); 601 config.configure(taglib, is, schema); 602 } catch (ConfigException e) { 603 log.warning(e.toString()); 604 log.log(Level.FINER, e.toString(), e); 605 606 taglib.setConfigException(e); 607 } catch (Exception e) { 608 log.warning(e.toString()); 609 log.log(Level.FINER, e.toString(), e); 610 611 taglib.setConfigException(e); 612 } finally { 613 is.close(); 614 } 615 616 623 624 return taglib; 625 } 626 627 632 private TldPreload parseTldPreload(Path path) 633 throws JspParseException, IOException 634 { 635 ReadStream is = path.openRead(); 636 637 try { 638 TldPreload taglib = parseTldPreload(is); 639 640 taglib.setPath(path); 641 String appDir = _webApp.getAppDir().getPath(); 642 String tagPath = path.getPath(); 643 644 if (tagPath.startsWith(appDir)) 645 taglib.setLocation(tagPath.substring(appDir.length())); 646 647 return taglib; 648 } finally { 649 is.close(); 650 } 651 } 652 653 658 private TldPreload parseTldPreload(InputStream is) 659 throws JspParseException, IOException 660 { 661 if (is instanceof ReadStream) { 662 Path path = ((ReadStream) is).getPath(); 663 664 path.setUserPath(path.getURL()); 665 } 666 667 String schema = null; 668 669 if (_webApp.getJsp() == null || 670 _webApp.getJsp().isValidateTaglibSchema()) { 671 schema = getSchema(); 672 } 673 674 TldPreload taglib = new TldPreload(); 675 try { 676 _config.configure(taglib, is, schema); 677 } catch (ConfigException e) { 678 log.warning(e.toString()); 679 log.log(Level.FINER, e.toString(), e); 680 681 taglib.setConfigException(e); 682 } catch (Exception e) { 683 log.warning(e.toString()); 684 log.log(Level.FINER, e.toString(), e); 685 686 taglib.setConfigException(e); 687 } finally { 688 is.close(); 689 } 690 691 return taglib; 692 } 693 694 701 private Path findJar(String location) 702 { 703 Path path; 704 705 if (location.startsWith("file:")) 706 path = Vfs.lookup(location); 707 else if (location.startsWith("/")) 708 path = _resourceManager.resolvePath("." + location); 709 else 710 path = _resourceManager.resolvePath(location); 711 712 if (path.exists()) 713 return path; 714 715 DynamicClassLoader loader; 716 loader = (DynamicClassLoader) Thread.currentThread().getContextClassLoader(); 717 String classPath = loader.getClassPath(); 718 char sep = CauchoSystem.getPathSeparatorChar(); 719 720 int head = 0; 721 int tail = 0; 722 723 while ((tail = classPath.indexOf(sep, head)) >= 0) { 724 String sub = classPath.substring(head, tail); 725 726 path = Vfs.lookup(sub); 727 728 if (sub.endsWith(location) && path.exists()) 729 return path; 730 731 head = tail + 1; 732 } 733 734 if (classPath.length() <= head) 735 return null; 736 737 String sub = classPath.substring(head); 738 739 path = Vfs.lookup(sub); 740 741 if (sub.endsWith(location) && path.exists()) 742 return path; 743 else 744 return null; 745 } 746 } 747 | Popular Tags |