Author: markt Date: Thu Nov 14 16:28:51 2013 New Revision: 1541962 URL: http://svn.apache.org/r1541962 Log: Check the parsed TLD cache entries are not stale.
Modified: tomcat/trunk/java/org/apache/jasper/JspC.java tomcat/trunk/java/org/apache/jasper/compiler/TldCache.java tomcat/trunk/java/org/apache/jasper/servlet/JasperInitializer.java Modified: tomcat/trunk/java/org/apache/jasper/JspC.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/JspC.java?rev=1541962&r1=1541961&r2=1541962&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/JspC.java (original) +++ tomcat/trunk/java/org/apache/jasper/JspC.java Thu Nov 14 16:28:51 2013 @@ -847,6 +847,10 @@ public class JspC extends Task implement org.apache.jasper.xmlparser.ParserUtils.validating=b; } + public boolean isValidateXml() { + return validateXml; + } + public void setListErrors( boolean b ) { listErrors = b; } @@ -1432,7 +1436,7 @@ public class JspC extends Task implement } catch (SAXException e) { throw new JasperException(e); } - tldCache = new TldCache(scanner.getUriTldResourcePathMap(), + tldCache = new TldCache(context, scanner.getUriTldResourcePathMap(), scanner.getTldResourcePathTaglibXmlMap()); context.setAttribute(TldCache.SERVLET_CONTEXT_ATTRIBUTE_NAME, tldCache); rctxt = new JspRuntimeContext(context, this); Modified: tomcat/trunk/java/org/apache/jasper/compiler/TldCache.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/TldCache.java?rev=1541962&r1=1541961&r2=1541962&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/TldCache.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/TldCache.java Thu Nov 14 16:28:51 2013 @@ -16,13 +16,22 @@ */ package org.apache.jasper.compiler; +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import javax.servlet.ServletContext; +import org.apache.jasper.JasperException; +import org.apache.jasper.servlet.JasperInitializer; import org.apache.tomcat.util.descriptor.tld.TaglibXml; +import org.apache.tomcat.util.descriptor.tld.TldParser; import org.apache.tomcat.util.descriptor.tld.TldResourcePath; +import org.apache.tomcat.util.scan.Jar; +import org.xml.sax.SAXException; /** * This class caches parsed instances of TLD files to remove the need for the @@ -35,8 +44,11 @@ public class TldCache { public static final String SERVLET_CONTEXT_ATTRIBUTE_NAME = TldCache.class.getName(); - private final Map<String, TldResourcePath> uriTldResourcePathMap = new HashMap<>(); - private final Map<TldResourcePath, TaglibXml> tldResourcePathTaglibXmlMap = new HashMap<>(); + private final ServletContext servletContext; + private final Map<String,TldResourcePath> uriTldResourcePathMap = new HashMap<>(); + private final Map<TldResourcePath,TaglibXmlCacheEntry> tldResourcePathTaglibXmlMap = + new HashMap<>(); + private final TldParser tldParser; public static TldCache getInstance(ServletContext servletContext) { @@ -48,10 +60,21 @@ public class TldCache { } - public TldCache(Map<String, TldResourcePath> uriTldResourcePathMap, + public TldCache(ServletContext servletContext, + Map<String, TldResourcePath> uriTldResourcePathMap, Map<TldResourcePath, TaglibXml> tldResourcePathTaglibXmlMap) { + this.servletContext = servletContext; this.uriTldResourcePathMap.putAll(uriTldResourcePathMap); - this.tldResourcePathTaglibXmlMap.putAll(tldResourcePathTaglibXmlMap); + for (Entry<TldResourcePath, TaglibXml> entry : tldResourcePathTaglibXmlMap.entrySet()) { + TldResourcePath tldResourcePath = entry.getKey(); + long lastModified[] = getLastModified(tldResourcePath); + TaglibXmlCacheEntry cacheEntry = new TaglibXmlCacheEntry( + entry.getValue(), lastModified[0], lastModified[1]); + this.tldResourcePathTaglibXmlMap.put(tldResourcePath, cacheEntry); + } + boolean validate = Boolean.parseBoolean( + servletContext.getInitParameter(JasperInitializer.VALIDATE)); + tldParser = new TldParser(true, validate); } @@ -60,7 +83,83 @@ public class TldCache { } - public TaglibXml getTaglibXml(TldResourcePath tldResourcePath) { - return tldResourcePathTaglibXmlMap.get(tldResourcePath); + public TaglibXml getTaglibXml(TldResourcePath tldResourcePath) throws JasperException { + TaglibXmlCacheEntry cacheEntry = tldResourcePathTaglibXmlMap.get(tldResourcePath); + long lastModified[] = getLastModified(tldResourcePath); + if (lastModified[0] != cacheEntry.getWebAppPathLastModified() || + lastModified[1] != cacheEntry.getEntryLastModified()) { + synchronized (cacheEntry) { + if (lastModified[0] != cacheEntry.getWebAppPathLastModified() || + lastModified[1] != cacheEntry.getEntryLastModified()) { + // Re-parse TLD + TaglibXml updatedTaglibXml; + try { + updatedTaglibXml = tldParser.parse(tldResourcePath); + } catch (IOException | SAXException e) { + throw new JasperException(e); + } + cacheEntry.setTaglibXml(updatedTaglibXml); + cacheEntry.setWebAppPathLastModified(lastModified[0]); + cacheEntry.setEntryLastModified(lastModified[1]); + } + } + } + return cacheEntry.getTaglibXml(); + } + + + private long[] getLastModified(TldResourcePath tldResourcePath) { + long[] result = new long[2]; + result[0] = -1; + result[1] = -1; + try { + URL url = servletContext.getResource(tldResourcePath.getWebappPath()); + URLConnection conn = url.openConnection(); + result[0] = conn.getLastModified(); + Jar jar = tldResourcePath.getJar(); + if (jar != null) { + result[1] = jar.getLastModified(tldResourcePath.getEntryName()); + } + } catch (IOException e) { + // Ignore (shouldn't happen) + } + return result; + } + + private static class TaglibXmlCacheEntry { + private volatile TaglibXml taglibXml; + private volatile long webAppPathLastModified; + private volatile long entryLastModified; + + public TaglibXmlCacheEntry(TaglibXml taglibXml, long webAppPathLastModified, + long entryLastModified) { + this.taglibXml = taglibXml; + this.webAppPathLastModified = webAppPathLastModified; + this.entryLastModified = entryLastModified; + } + + public TaglibXml getTaglibXml() { + return taglibXml; + } + + public void setTaglibXml(TaglibXml taglibXml) { + this.taglibXml = taglibXml; + } + + public long getWebAppPathLastModified() { + return webAppPathLastModified; + } + + public void setWebAppPathLastModified(long webAppPathLastModified) { + this.webAppPathLastModified = webAppPathLastModified; + } + + public long getEntryLastModified() { + return entryLastModified; + } + + public void setEntryLastModified(long entryLastModified) { + this.entryLastModified = entryLastModified; + } } } Modified: tomcat/trunk/java/org/apache/jasper/servlet/JasperInitializer.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/servlet/JasperInitializer.java?rev=1541962&r1=1541961&r2=1541962&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/servlet/JasperInitializer.java (original) +++ tomcat/trunk/java/org/apache/jasper/servlet/JasperInitializer.java Thu Nov 14 16:28:51 2013 @@ -63,7 +63,7 @@ public class JasperInitializer implement } context.setAttribute(TldCache.SERVLET_CONTEXT_ATTRIBUTE_NAME, - new TldCache(scanner.getUriTldResourcePathMap(), + new TldCache(context, scanner.getUriTldResourcePathMap(), scanner.getTldResourcePathTaglibXmlMap())); } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org