1 17 18 package org.apache.jasper.compiler; 19 20 import java.io.InputStream ; 21 import java.io.IOException ; 22 import java.net.JarURLConnection ; 23 import java.net.MalformedURLException ; 24 import java.net.URL ; 25 import java.net.URLClassLoader ; 26 import java.net.URLConnection ; 27 import java.util.Enumeration ; 28 import java.util.Hashtable ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 import java.util.Set ; 32 import java.util.StringTokenizer ; 33 import java.util.jar.JarEntry ; 34 import java.util.jar.JarFile ; 35 import org.xml.sax.InputSource ; 36 37 import javax.servlet.ServletContext ; 38 39 import org.apache.commons.logging.Log; 40 import org.apache.commons.logging.LogFactory; 41 import org.apache.jasper.Constants; 42 import org.apache.jasper.JasperException; 43 import org.apache.jasper.xmlparser.ParserUtils; 44 import org.apache.jasper.xmlparser.TreeNode; 45 46 78 79 public class TldLocationsCache { 80 81 private Log log = LogFactory.getLog(TldLocationsCache.class); 83 84 87 public static final int ABS_URI = 0; 88 public static final int ROOT_REL_URI = 1; 89 public static final int NOROOT_REL_URI = 2; 90 91 private static final String WEB_XML = "/WEB-INF/web.xml"; 92 private static final String FILE_PROTOCOL = "file:"; 93 private static final String JAR_FILE_SUFFIX = ".jar"; 94 95 private static HashSet noTldJars; 97 98 105 private Hashtable mappings; 106 107 private boolean initialized; 108 private ServletContext ctxt; 109 private boolean redeployMode; 110 111 114 117 static { 118 noTldJars = new HashSet (); 119 noTldJars.add("ant.jar"); 120 noTldJars.add("catalina.jar"); 121 noTldJars.add("catalina-ant.jar"); 122 noTldJars.add("catalina-cluster.jar"); 123 noTldJars.add("catalina-optional.jar"); 124 noTldJars.add("catalina-i18n-fr.jar"); 125 noTldJars.add("catalina-i18n-ja.jar"); 126 noTldJars.add("catalina-i18n-es.jar"); 127 noTldJars.add("commons-dbcp.jar"); 128 noTldJars.add("commons-modeler.jar"); 129 noTldJars.add("commons-logging-api.jar"); 130 noTldJars.add("commons-beanutils.jar"); 131 noTldJars.add("commons-fileupload-1.0.jar"); 132 noTldJars.add("commons-pool.jar"); 133 noTldJars.add("commons-digester.jar"); 134 noTldJars.add("commons-logging.jar"); 135 noTldJars.add("commons-collections.jar"); 136 noTldJars.add("commons-el.jar"); 137 noTldJars.add("jakarta-regexp-1.2.jar"); 138 noTldJars.add("jasper-compiler.jar"); 139 noTldJars.add("jasper-runtime.jar"); 140 noTldJars.add("jmx.jar"); 141 noTldJars.add("jmx-tools.jar"); 142 noTldJars.add("jsp-api.jar"); 143 noTldJars.add("jkshm.jar"); 144 noTldJars.add("jkconfig.jar"); 145 noTldJars.add("naming-common.jar"); 146 noTldJars.add("naming-resources.jar"); 147 noTldJars.add("naming-factory.jar"); 148 noTldJars.add("naming-java.jar"); 149 noTldJars.add("servlet-api.jar"); 150 noTldJars.add("servlets-default.jar"); 151 noTldJars.add("servlets-invoker.jar"); 152 noTldJars.add("servlets-common.jar"); 153 noTldJars.add("servlets-webdav.jar"); 154 noTldJars.add("tomcat-util.jar"); 155 noTldJars.add("tomcat-http11.jar"); 156 noTldJars.add("tomcat-jni.jar"); 157 noTldJars.add("tomcat-jk.jar"); 158 noTldJars.add("tomcat-jk2.jar"); 159 noTldJars.add("tomcat-coyote.jar"); 160 noTldJars.add("xercesImpl.jar"); 161 noTldJars.add("xmlParserAPIs.jar"); 162 noTldJars.add("xml-apis.jar"); 163 noTldJars.add("sunjce_provider.jar"); 165 noTldJars.add("ldapsec.jar"); 166 noTldJars.add("localedata.jar"); 167 noTldJars.add("dnsns.jar"); 168 } 169 170 public TldLocationsCache(ServletContext ctxt) { 171 this(ctxt, true); 172 } 173 174 184 public TldLocationsCache(ServletContext ctxt, boolean redeployMode) { 185 this.ctxt = ctxt; 186 this.redeployMode = redeployMode; 187 mappings = new Hashtable (); 188 initialized = false; 189 } 190 191 197 public static void setNoTldJars(String jarNames) { 198 if (jarNames != null) { 199 noTldJars.clear(); 200 StringTokenizer tokenizer = new StringTokenizer (jarNames, ","); 201 while (tokenizer.hasMoreElements()) { 202 noTldJars.add(tokenizer.nextToken()); 203 } 204 } 205 } 206 207 223 public String [] getLocation(String uri) throws JasperException { 224 if (!initialized) { 225 init(); 226 } 227 return (String []) mappings.get(uri); 228 } 229 230 236 public static int uriType(String uri) { 237 if (uri.indexOf(':') != -1) { 238 return ABS_URI; 239 } else if (uri.startsWith("/")) { 240 return ROOT_REL_URI; 241 } else { 242 return NOROOT_REL_URI; 243 } 244 } 245 246 private void init() throws JasperException { 247 if (initialized) return; 248 try { 249 processWebDotXml(); 250 scanJars(); 251 processTldsInFileSystem("/WEB-INF/"); 252 initialized = true; 253 } catch (Exception ex) { 254 throw new JasperException(Localizer.getMessage( 255 "jsp.error.internal.tldinit", ex.getMessage())); 256 } 257 } 258 259 262 private void processWebDotXml() throws Exception { 263 264 InputStream is = null; 265 266 try { 267 String altDDName = (String )ctxt.getAttribute( 269 Constants.ALT_DD_ATTR); 270 URL uri = null; 271 if (altDDName != null) { 272 try { 273 uri = new URL (FILE_PROTOCOL+altDDName.replace('\\', '/')); 274 } catch (MalformedURLException e) { 275 if (log.isWarnEnabled()) { 276 log.warn(Localizer.getMessage( 277 "jsp.error.internal.filenotfound", 278 altDDName)); 279 } 280 } 281 } else { 282 uri = ctxt.getResource(WEB_XML); 283 if (uri == null && log.isWarnEnabled()) { 284 log.warn(Localizer.getMessage( 285 "jsp.error.internal.filenotfound", 286 WEB_XML)); 287 } 288 } 289 290 if (uri == null) { 291 return; 292 } 293 is = uri.openStream(); 294 InputSource ip = new InputSource (is); 295 ip.setSystemId(uri.toExternalForm()); 296 297 TreeNode webtld = null; 299 if (altDDName != null) { 301 webtld = new ParserUtils().parseXMLDocument(altDDName, ip); 302 } else { 303 webtld = new ParserUtils().parseXMLDocument(WEB_XML, ip); 304 } 305 306 TreeNode jspConfig = webtld.findChild("jsp-config"); 308 if (jspConfig != null) { 309 webtld = jspConfig; 310 } 311 Iterator taglibs = webtld.findChildren("taglib"); 312 while (taglibs.hasNext()) { 313 314 TreeNode taglib = (TreeNode) taglibs.next(); 316 String tagUri = null; 317 String tagLoc = null; 318 TreeNode child = taglib.findChild("taglib-uri"); 319 if (child != null) 320 tagUri = child.getBody(); 321 child = taglib.findChild("taglib-location"); 322 if (child != null) 323 tagLoc = child.getBody(); 324 325 if (tagLoc == null) 327 continue; 328 if (uriType(tagLoc) == NOROOT_REL_URI) 329 tagLoc = "/WEB-INF/" + tagLoc; 330 String tagLoc2 = null; 331 if (tagLoc.endsWith(JAR_FILE_SUFFIX)) { 332 tagLoc = ctxt.getResource(tagLoc).toString(); 333 tagLoc2 = "META-INF/taglib.tld"; 334 } 335 mappings.put(tagUri, new String [] { tagLoc, tagLoc2 }); 336 } 337 } finally { 338 if (is != null) { 339 try { 340 is.close(); 341 } catch (Throwable t) {} 342 } 343 } 344 } 345 346 355 private void scanJar(JarURLConnection conn, boolean ignore) 356 throws JasperException { 357 358 JarFile jarFile = null; 359 String resourcePath = conn.getJarFileURL().toString(); 360 try { 361 if (redeployMode) { 362 conn.setUseCaches(false); 363 } 364 jarFile = conn.getJarFile(); 365 Enumeration entries = jarFile.entries(); 366 while (entries.hasMoreElements()) { 367 JarEntry entry = (JarEntry ) entries.nextElement(); 368 String name = entry.getName(); 369 if (!name.startsWith("META-INF/")) continue; 370 if (!name.endsWith(".tld")) continue; 371 InputStream stream = jarFile.getInputStream(entry); 372 try { 373 String uri = getUriFromTld(resourcePath, stream); 374 if (uri != null && mappings.get(uri) == null) { 377 mappings.put(uri, new String []{ resourcePath, name }); 378 } 379 } finally { 380 if (stream != null) { 381 try { 382 stream.close(); 383 } catch (Throwable t) { 384 } 386 } 387 } 388 } 389 } catch (Exception ex) { 390 if (!redeployMode) { 391 if (jarFile != null) { 393 try { 394 jarFile.close(); 395 } catch (Throwable t) { 396 } 398 } 399 } 400 if (!ignore) { 401 throw new JasperException(ex); 402 } 403 } finally { 404 if (redeployMode) { 405 if (jarFile != null) { 407 try { 408 jarFile.close(); 409 } catch (Throwable t) { 410 } 412 } 413 } 414 } 415 } 416 417 422 private void processTldsInFileSystem(String startPath) 423 throws Exception { 424 425 Set dirList = ctxt.getResourcePaths(startPath); 426 if (dirList != null) { 427 Iterator it = dirList.iterator(); 428 while (it.hasNext()) { 429 String path = (String ) it.next(); 430 if (path.endsWith("/")) { 431 processTldsInFileSystem(path); 432 } 433 if (!path.endsWith(".tld")) { 434 continue; 435 } 436 InputStream stream = ctxt.getResourceAsStream(path); 437 String uri = null; 438 try { 439 uri = getUriFromTld(path, stream); 440 } finally { 441 if (stream != null) { 442 try { 443 stream.close(); 444 } catch (Throwable t) { 445 } 447 } 448 } 449 if (uri != null && mappings.get(uri) == null) { 452 mappings.put(uri, new String [] { path, null }); 453 } 454 } 455 } 456 } 457 458 462 private String getUriFromTld(String resourcePath, InputStream in) 463 throws JasperException 464 { 465 TreeNode tld = new ParserUtils().parseXMLDocument(resourcePath, in); 467 TreeNode uri = tld.findChild("uri"); 468 if (uri != null) { 469 String body = uri.getBody(); 470 if (body != null) 471 return body; 472 } 473 474 return null; 475 } 476 477 496 private void scanJars() throws Exception { 497 498 ClassLoader webappLoader 499 = Thread.currentThread().getContextClassLoader(); 500 ClassLoader loader = webappLoader; 501 502 while (loader != null) { 503 if (loader instanceof URLClassLoader ) { 504 URL [] urls = ((URLClassLoader ) loader).getURLs(); 505 for (int i=0; i<urls.length; i++) { 506 URLConnection conn = urls[i].openConnection(); 507 if (conn instanceof JarURLConnection ) { 508 if (needScanJar(loader, webappLoader, 509 ((JarURLConnection ) conn).getJarFile().getName())) { 510 scanJar((JarURLConnection ) conn, true); 511 } 512 } else { 513 String urlStr = urls[i].toString(); 514 if (urlStr.startsWith(FILE_PROTOCOL) 515 && urlStr.endsWith(JAR_FILE_SUFFIX) 516 && needScanJar(loader, webappLoader, urlStr)) { 517 URL jarURL = new URL ("jar:" + urlStr + "!/"); 518 scanJar((JarURLConnection ) jarURL.openConnection(), 519 true); 520 } 521 } 522 } 523 } 524 525 loader = loader.getParent(); 526 } 527 } 528 529 540 private boolean needScanJar(ClassLoader loader, ClassLoader webappLoader, 541 String jarPath) { 542 if (loader == webappLoader) { 543 return true; 546 } else { 547 String jarName = jarPath; 548 int slash = jarPath.lastIndexOf('/'); 549 if (slash >= 0) { 550 jarName = jarPath.substring(slash + 1); 551 } 552 return (!noTldJars.contains(jarName)); 553 } 554 } 555 } 556 | Popular Tags |