1
17 package org.apache.jasper.compiler;
18
19 import java.io.IOException;
20 import java.net.URL;
21 import java.net.URLConnection;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.Map.Entry;
25
26 import javax.servlet.ServletContext;
27
28 import org.apache.jasper.Constants;
29 import org.apache.jasper.JasperException;
30 import org.apache.tomcat.Jar;
31 import org.apache.tomcat.util.descriptor.tld.TaglibXml;
32 import org.apache.tomcat.util.descriptor.tld.TldParser;
33 import org.apache.tomcat.util.descriptor.tld.TldResourcePath;
34 import org.xml.sax.SAXException;
35
36
42 public class TldCache {
43
44 public static final String SERVLET_CONTEXT_ATTRIBUTE_NAME =
45 TldCache.class.getName();
46
47 private final ServletContext servletContext;
48 private final Map<String,TldResourcePath> uriTldResourcePathMap = new HashMap<>();
49 private final Map<TldResourcePath,TaglibXmlCacheEntry> tldResourcePathTaglibXmlMap =
50 new HashMap<>();
51 private final TldParser tldParser;
52
53
54 public static TldCache getInstance(ServletContext servletContext) {
55 if (servletContext == null) {
56 throw new IllegalArgumentException(Localizer.getMessage(
57 "org.apache.jasper.compiler.TldCache.servletContextNull"));
58 }
59 return (TldCache) servletContext.getAttribute(SERVLET_CONTEXT_ATTRIBUTE_NAME);
60 }
61
62
63 public TldCache(ServletContext servletContext,
64 Map<String, TldResourcePath> uriTldResourcePathMap,
65 Map<TldResourcePath, TaglibXml> tldResourcePathTaglibXmlMap) {
66 this.servletContext = servletContext;
67 this.uriTldResourcePathMap.putAll(uriTldResourcePathMap);
68 for (Entry<TldResourcePath, TaglibXml> entry : tldResourcePathTaglibXmlMap.entrySet()) {
69 TldResourcePath tldResourcePath = entry.getKey();
70 long lastModified[] = getLastModified(tldResourcePath);
71 TaglibXmlCacheEntry cacheEntry = new TaglibXmlCacheEntry(
72 entry.getValue(), lastModified[0], lastModified[1]);
73 this.tldResourcePathTaglibXmlMap.put(tldResourcePath, cacheEntry);
74 }
75 boolean validate = Boolean.parseBoolean(
76 servletContext.getInitParameter(Constants.XML_VALIDATION_TLD_INIT_PARAM));
77 String blockExternalString = servletContext.getInitParameter(
78 Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
79 boolean blockExternal;
80 if (blockExternalString == null) {
81 blockExternal = true;
82 } else {
83 blockExternal = Boolean.parseBoolean(blockExternalString);
84 }
85 tldParser = new TldParser(true, validate, blockExternal);
86 }
87
88
89 public TldResourcePath getTldResourcePath(String uri) {
90 return uriTldResourcePathMap.get(uri);
91 }
92
93
94 public TaglibXml getTaglibXml(TldResourcePath tldResourcePath) throws JasperException {
95 TaglibXmlCacheEntry cacheEntry = tldResourcePathTaglibXmlMap.get(tldResourcePath);
96 if (cacheEntry == null) {
97 return null;
98 }
99 long lastModified[] = getLastModified(tldResourcePath);
100 if (lastModified[0] != cacheEntry.getWebAppPathLastModified() ||
101 lastModified[1] != cacheEntry.getEntryLastModified()) {
102 synchronized (cacheEntry) {
103 if (lastModified[0] != cacheEntry.getWebAppPathLastModified() ||
104 lastModified[1] != cacheEntry.getEntryLastModified()) {
105
106 TaglibXml updatedTaglibXml;
107 try {
108 updatedTaglibXml = tldParser.parse(tldResourcePath);
109 } catch (IOException | SAXException e) {
110 throw new JasperException(e);
111 }
112 cacheEntry.setTaglibXml(updatedTaglibXml);
113 cacheEntry.setWebAppPathLastModified(lastModified[0]);
114 cacheEntry.setEntryLastModified(lastModified[1]);
115 }
116 }
117 }
118 return cacheEntry.getTaglibXml();
119 }
120
121
122 private long[] getLastModified(TldResourcePath tldResourcePath) {
123 long[] result = new long[2];
124 result[0] = -1;
125 result[1] = -1;
126 try {
127 String webappPath = tldResourcePath.getWebappPath();
128 if (webappPath != null) {
129
130
131 URL url = servletContext.getResource(tldResourcePath.getWebappPath());
132 URLConnection conn = url.openConnection();
133 result[0] = conn.getLastModified();
134 if ("file".equals(url.getProtocol())) {
135
136
137
138 conn.getInputStream().close();
139 }
140 }
141 try (Jar jar = tldResourcePath.openJar()) {
142 if (jar != null) {
143 result[1] = jar.getLastModified(tldResourcePath.getEntryName());
144 }
145 }
146 } catch (IOException e) {
147
148 }
149 return result;
150 }
151
152 private static class TaglibXmlCacheEntry {
153 private volatile TaglibXml taglibXml;
154 private volatile long webAppPathLastModified;
155 private volatile long entryLastModified;
156
157 public TaglibXmlCacheEntry(TaglibXml taglibXml, long webAppPathLastModified,
158 long entryLastModified) {
159 this.taglibXml = taglibXml;
160 this.webAppPathLastModified = webAppPathLastModified;
161 this.entryLastModified = entryLastModified;
162 }
163
164 public TaglibXml getTaglibXml() {
165 return taglibXml;
166 }
167
168 public void setTaglibXml(TaglibXml taglibXml) {
169 this.taglibXml = taglibXml;
170 }
171
172 public long getWebAppPathLastModified() {
173 return webAppPathLastModified;
174 }
175
176 public void setWebAppPathLastModified(long webAppPathLastModified) {
177 this.webAppPathLastModified = webAppPathLastModified;
178 }
179
180 public long getEntryLastModified() {
181 return entryLastModified;
182 }
183
184 public void setEntryLastModified(long entryLastModified) {
185 this.entryLastModified = entryLastModified;
186 }
187 }
188 }
189