1 17 18 19 package org.apache.catalina.startup; 20 21 22 import java.io.File ; 23 import java.io.FileInputStream ; 24 import java.io.FileOutputStream ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.ObjectInputStream ; 28 import java.io.ObjectOutputStream ; 29 import java.net.URL ; 30 import java.net.URLClassLoader ; 31 import java.util.ArrayList ; 32 import java.util.Enumeration ; 33 import java.util.HashMap ; 34 import java.util.HashSet ; 35 import java.util.Iterator ; 36 import java.util.Map ; 37 import java.util.Set ; 38 import java.util.StringTokenizer ; 39 import java.util.jar.JarEntry ; 40 import java.util.jar.JarFile ; 41 42 import javax.naming.NameClassPair ; 43 import javax.naming.NamingEnumeration ; 44 import javax.naming.NamingException ; 45 import javax.naming.directory.DirContext ; 46 import javax.servlet.ServletException ; 47 48 import org.apache.catalina.Context; 49 import org.apache.catalina.Globals; 50 import org.apache.catalina.core.StandardContext; 51 import org.apache.catalina.util.StringManager; 52 import org.apache.tomcat.util.digester.Digester; 53 import org.xml.sax.InputSource ; 54 55 63 public final class TldConfig { 64 65 private static HashSet noTldJars; 67 68 private static org.apache.commons.logging.Log log= 69 org.apache.commons.logging.LogFactory.getLog( TldConfig.class ); 70 71 private static final String FILE_URL_PREFIX = "file:"; 72 private static final int FILE_URL_PREFIX_LEN = FILE_URL_PREFIX.length(); 73 74 75 78 static { 79 noTldJars = new HashSet (); 80 noTldJars.add("catalina.jar"); 81 noTldJars.add("catalina-ant.jar"); 82 noTldJars.add("catalina-cluster.jar"); 83 noTldJars.add("catalina-optional.jar"); 84 noTldJars.add("commons-el.jar"); 85 noTldJars.add("commons-logging-api.jar"); 86 noTldJars.add("commons-modeler.jar"); 87 noTldJars.add("jasper-compiler.jar"); 88 noTldJars.add("jasper-compiler-jdt.jar"); 89 noTldJars.add("jasper-runtime.jar"); 90 noTldJars.add("jsp-api.jar"); 91 noTldJars.add("naming-resources.jar"); 92 noTldJars.add("naming-factory.jar"); 93 noTldJars.add("naming-factory-dbcp.jar"); 94 noTldJars.add("servlet-api.jar"); 95 noTldJars.add("servlets-cgi.jar"); 96 noTldJars.add("servlets-default.jar"); 97 noTldJars.add("servlets-invoker.jar"); 98 noTldJars.add("servlets-ssi.jar"); 99 noTldJars.add("servlets-webdav.jar"); 100 noTldJars.add("tomcat-ajp.jar"); 101 noTldJars.add("tomcat-coyote.jar"); 102 noTldJars.add("tomcat-http.jar"); 103 noTldJars.add("tomcat-util.jar"); 104 noTldJars.add("catalina-i18n-en.jar"); 106 noTldJars.add("catalina-i18n-es.jar"); 107 noTldJars.add("catalina-i18n-fr.jar"); 108 noTldJars.add("catalina-i18n-ja.jar"); 109 noTldJars.add("ant.jar"); 111 noTldJars.add("commons-dbcp.jar"); 112 noTldJars.add("commons-beanutils.jar"); 113 noTldJars.add("commons-fileupload-1.0.jar"); 114 noTldJars.add("commons-pool.jar"); 115 noTldJars.add("commons-digester.jar"); 116 noTldJars.add("commons-logging.jar"); 117 noTldJars.add("commons-collections.jar"); 118 noTldJars.add("jmx.jar"); 119 noTldJars.add("jmx-tools.jar"); 120 noTldJars.add("xercesImpl.jar"); 121 noTldJars.add("xmlParserAPIs.jar"); 122 noTldJars.add("xml-apis.jar"); 123 noTldJars.add("sunjce_provider.jar"); 125 noTldJars.add("ldapsec.jar"); 126 noTldJars.add("localedata.jar"); 127 noTldJars.add("dnsns.jar"); 128 } 129 130 131 133 136 private Context context = null; 137 138 139 142 private static final StringManager sm = 143 StringManager.getManager(Constants.Package); 144 145 149 private static Digester tldDigester = null; 150 151 152 155 private static boolean tldValidation = false; 156 157 158 161 private static boolean tldNamespaceAware = false; 162 163 private boolean rescan=true; 164 165 private ArrayList listeners=new ArrayList (); 166 167 169 175 public static void setNoTldJars(String jarNames) { 176 if (jarNames != null) { 177 noTldJars.clear(); 178 StringTokenizer tokenizer = new StringTokenizer (jarNames, ","); 179 while (tokenizer.hasMoreElements()) { 180 noTldJars.add(tokenizer.nextToken()); 181 } 182 } 183 } 184 185 190 public void setTldValidation(boolean tldValidation){ 191 TldConfig.tldValidation = tldValidation; 192 } 193 194 199 public boolean getTldValidation(){ 200 return tldValidation; 201 } 202 203 208 public boolean getTldNamespaceAware(){ 209 return tldNamespaceAware; 210 } 211 212 213 218 public void setTldNamespaceAware(boolean tldNamespaceAware){ 219 TldConfig.tldNamespaceAware = tldNamespaceAware; 220 } 221 222 223 public boolean isRescan() { 224 return rescan; 225 } 226 227 public void setRescan(boolean rescan) { 228 this.rescan = rescan; 229 } 230 231 public Context getContext() { 232 return context; 233 } 234 235 public void setContext(Context context) { 236 this.context = context; 237 } 238 239 public void addApplicationListener( String s ) { 240 log.debug( "Add tld listener " + s); 242 listeners.add(s); 243 } 244 245 public String [] getTldListeners() { 246 String result[]=new String [listeners.size()]; 247 listeners.toArray(result); 248 return result; 249 } 250 251 252 258 public void execute() throws Exception { 259 long t1=System.currentTimeMillis(); 260 261 File tldCache=null; 262 263 if (context instanceof StandardContext) { 264 File workDir= (File ) 265 ((StandardContext)context).getServletContext().getAttribute(Globals.WORK_DIR_ATTR); 266 tldCache=new File ( workDir, "tldCache.ser"); 267 } 268 269 if( ! rescan ) { 271 if( tldCache!= null && tldCache.exists()) { 273 processCache(tldCache); 275 return; 276 } 277 } 278 279 283 Set resourcePaths = tldScanResourcePaths(); 284 Map jarPaths = getJarPaths(); 285 286 if (tldCache != null && tldCache.exists()) { 288 long lastModified = getLastModified(resourcePaths, jarPaths); 289 if (lastModified < tldCache.lastModified()) { 290 processCache(tldCache); 291 return; 292 } 293 } 294 295 Iterator paths = resourcePaths.iterator(); 297 while (paths.hasNext()) { 298 String path = (String ) paths.next(); 299 if (path.endsWith(".jar")) { 300 tldScanJar(path); 301 } else { 302 tldScanTld(path); 303 } 304 } 305 if (jarPaths != null) { 306 paths = jarPaths.values().iterator(); 307 while (paths.hasNext()) { 308 tldScanJar((File ) paths.next()); 309 } 310 } 311 312 String list[] = getTldListeners(); 313 314 if( tldCache!= null ) { 315 log.debug( "Saving tld cache: " + tldCache + " " + list.length); 316 try { 317 FileOutputStream out=new FileOutputStream (tldCache); 318 ObjectOutputStream oos=new ObjectOutputStream ( out ); 319 oos.writeObject( list ); 320 oos.close(); 321 } catch( IOException ex ) { 322 ex.printStackTrace(); 323 } 324 } 325 326 if( log.isDebugEnabled() ) 327 log.debug( "Adding tld listeners:" + list.length); 328 for( int i=0; list!=null && i<list.length; i++ ) { 329 context.addApplicationListener(list[i]); 330 } 331 332 long t2=System.currentTimeMillis(); 333 if( context instanceof StandardContext ) { 334 ((StandardContext)context).setTldScanTime(t2-t1); 335 } 336 337 } 338 339 341 349 private long getLastModified(Set resourcePaths, Map jarPaths) 350 throws Exception { 351 352 long lastModified = 0; 353 354 Iterator paths = resourcePaths.iterator(); 355 while (paths.hasNext()) { 356 String path = (String ) paths.next(); 357 URL url = context.getServletContext().getResource(path); 358 if (url == null) { 359 log.debug( "Null url "+ path ); 360 break; 361 } 362 long lastM = url.openConnection().getLastModified(); 363 if (lastM > lastModified) lastModified = lastM; 364 if (log.isDebugEnabled()) { 365 log.debug( "Last modified " + path + " " + lastM); 366 } 367 } 368 369 if (jarPaths != null) { 370 paths = jarPaths.values().iterator(); 371 while (paths.hasNext()) { 372 File jarFile = (File ) paths.next(); 373 long lastM = jarFile.lastModified(); 374 if (lastM > lastModified) lastModified = lastM; 375 if (log.isDebugEnabled()) { 376 log.debug("Last modified " + jarFile.getAbsolutePath() 377 + " " + lastM); 378 } 379 } 380 } 381 382 return lastModified; 383 } 384 385 private void processCache(File tldCache ) throws IOException { 386 try { 388 FileInputStream in=new FileInputStream (tldCache); 389 ObjectInputStream ois=new ObjectInputStream ( in ); 390 String list[]=(String [])ois.readObject(); 391 if( log.isDebugEnabled() ) 392 log.debug("Reusing tldCache " + tldCache + " " + list.length); 393 for( int i=0; list!=null && i<list.length; i++ ) { 394 context.addApplicationListener(list[i]); 395 } 396 ois.close(); 397 } catch( ClassNotFoundException ex ) { 398 ex.printStackTrace(); 399 } 400 } 401 402 407 private static Digester createTldDigester() { 408 409 return DigesterFactory.newDigester(tldValidation, 410 tldNamespaceAware, 411 new TldRuleSet()); 412 413 } 414 415 416 425 private void tldScanJar(String resourcePath) throws Exception { 426 427 if (log.isDebugEnabled()) { 428 log.debug(" Scanning JAR at resource path '" + resourcePath + "'"); 429 } 430 431 URL url = context.getServletContext().getResource(resourcePath); 432 if (url == null) { 433 throw new IllegalArgumentException 434 (sm.getString("contextConfig.tldResourcePath", 435 resourcePath)); 436 } 437 438 File file = new File (url.getFile()); 439 file = file.getCanonicalFile(); 440 tldScanJar(file); 441 442 } 443 444 450 private void tldScanJar(File file) throws Exception { 451 452 JarFile jarFile = null; 453 String name = null; 454 455 String jarPath = file.getAbsolutePath(); 456 457 try { 458 jarFile = new JarFile (file); 459 Enumeration entries = jarFile.entries(); 460 while (entries.hasMoreElements()) { 461 JarEntry entry = (JarEntry ) entries.nextElement(); 462 name = entry.getName(); 463 if (!name.startsWith("META-INF/")) { 464 continue; 465 } 466 if (!name.endsWith(".tld")) { 467 continue; 468 } 469 if (log.isTraceEnabled()) { 470 log.trace(" Processing TLD at '" + name + "'"); 471 } 472 try { 473 tldScanStream(new InputSource (jarFile.getInputStream(entry))); 474 } catch (Exception e) { 475 log.error(sm.getString("contextConfig.tldEntryException", 476 name, jarPath, context.getPath()), 477 e); 478 } 479 } 480 } catch (Exception e) { 481 log.error(sm.getString("contextConfig.tldJarException", 482 jarPath, context.getPath()), 483 e); 484 } finally { 485 if (jarFile != null) { 486 try { 487 jarFile.close(); 488 } catch (Throwable t) { 489 } 491 } 492 } 493 } 494 495 505 private void tldScanStream(InputSource resourceStream) 506 throws Exception { 507 508 if (tldDigester == null){ 509 tldDigester = createTldDigester(); 510 } 511 512 synchronized (tldDigester) { 513 try { 514 tldDigester.push(this); 515 tldDigester.parse(resourceStream); 516 } finally { 517 tldDigester.reset(); 518 } 519 } 520 521 } 522 523 531 private void tldScanTld(String resourcePath) throws Exception { 532 533 if (log.isDebugEnabled()) { 534 log.debug(" Scanning TLD at resource path '" + resourcePath + "'"); 535 } 536 537 InputSource inputSource = null; 538 try { 539 InputStream stream = 540 context.getServletContext().getResourceAsStream(resourcePath); 541 if (stream == null) { 542 throw new IllegalArgumentException 543 (sm.getString("contextConfig.tldResourcePath", 544 resourcePath)); 545 } 546 inputSource = new InputSource (stream); 547 if (inputSource == null) { 548 throw new IllegalArgumentException 549 (sm.getString("contextConfig.tldResourcePath", 550 resourcePath)); 551 } 552 tldScanStream(inputSource); 553 } catch (Exception e) { 554 throw new ServletException 555 (sm.getString("contextConfig.tldFileException", resourcePath, 556 context.getPath()), 557 e); 558 } 559 560 } 561 562 572 private Set tldScanResourcePaths() throws IOException { 573 if (log.isDebugEnabled()) { 574 log.debug(" Accumulating TLD resource paths"); 575 } 576 Set resourcePaths = new HashSet (); 577 578 if (log.isTraceEnabled()) { 581 log.trace(" Scanning <taglib> elements in web.xml"); 582 } 583 String taglibs[] = context.findTaglibs(); 584 for (int i = 0; i < taglibs.length; i++) { 585 String resourcePath = context.findTaglib(taglibs[i]); 586 if (!resourcePath.startsWith("/")) { 589 resourcePath = "/WEB-INF/" + resourcePath; 590 } 591 if (log.isTraceEnabled()) { 592 log.trace(" Adding path '" + resourcePath + 593 "' for URI '" + taglibs[i] + "'"); 594 } 595 resourcePaths.add(resourcePath); 596 } 597 598 DirContext resources = context.getResources(); 599 if (resources != null) { 600 tldScanResourcePathsWebInf(resources, "/WEB-INF", resourcePaths); 601 } 602 603 return (resourcePaths); 605 606 } 607 608 621 private void tldScanResourcePathsWebInf(DirContext resources, 622 String rootPath, 623 Set tldPaths) 624 throws IOException { 625 626 if (log.isTraceEnabled()) { 627 log.trace(" Scanning TLDs in " + rootPath + " subdirectory"); 628 } 629 630 try { 631 NamingEnumeration items = resources.list(rootPath); 632 while (items.hasMoreElements()) { 633 NameClassPair item = (NameClassPair ) items.nextElement(); 634 String resourcePath = rootPath + "/" + item.getName(); 635 if (!resourcePath.endsWith(".tld") 636 && (resourcePath.startsWith("/WEB-INF/classes") 637 || resourcePath.startsWith("/WEB-INF/lib"))) { 638 continue; 639 } 640 if (resourcePath.endsWith(".tld")) { 641 if (log.isTraceEnabled()) { 642 log.trace(" Adding path '" + resourcePath + "'"); 643 } 644 tldPaths.add(resourcePath); 645 } else { 646 tldScanResourcePathsWebInf(resources, resourcePath, 647 tldPaths); 648 } 649 } 650 } catch (NamingException e) { 651 ; } 653 } 654 655 675 private Map getJarPaths() { 676 677 HashMap jarPathMap = null; 678 679 ClassLoader webappLoader = Thread.currentThread().getContextClassLoader(); 680 ClassLoader loader = webappLoader; 681 while (loader != null) { 682 if (loader instanceof URLClassLoader ) { 683 URL [] urls = ((URLClassLoader ) loader).getURLs(); 684 for (int i=0; i<urls.length; i++) { 685 File file = new File (urls[i].getFile()); 690 try { 691 file = file.getCanonicalFile(); 692 } catch (IOException e) { 693 } 695 if (!file.exists()) { 696 continue; 697 } 698 String path = file.getAbsolutePath(); 699 if (!path.endsWith(".jar")) { 700 continue; 701 } 702 706 if (loader == webappLoader 707 || noTldJars == null 708 || !noTldJars.contains(file.getName())) { 709 if (jarPathMap == null) { 710 jarPathMap = new HashMap (); 711 jarPathMap.put(path, file); 712 } else if (!jarPathMap.containsKey(path)) { 713 jarPathMap.put(path, file); 714 } 715 } 716 } 717 } 718 loader = loader.getParent(); 719 } 720 721 return jarPathMap; 722 } 723 } 724 | Popular Tags |