1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.webapp;
20
21
22 import java.net.URI;
23 import java.net.URL;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.concurrent.ConcurrentHashMap;
30
31 import org.eclipse.jetty.util.log.Log;
32 import org.eclipse.jetty.util.log.Logger;
33 import org.eclipse.jetty.util.resource.EmptyResource;
34 import org.eclipse.jetty.util.resource.Resource;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class MetaInfConfiguration extends AbstractConfiguration
53 {
54 private static final Logger LOG = Log.getLogger(MetaInfConfiguration.class);
55
56 public static final String USE_CONTAINER_METAINF_CACHE = "org.eclipse.jetty.metainf.useCache";
57 public static final boolean DEFAULT_USE_CONTAINER_METAINF_CACHE = true;
58 public static final String CACHED_CONTAINER_TLDS = "org.eclipse.jetty.tlds.cache";
59 public static final String CACHED_CONTAINER_FRAGMENTS = FragmentConfiguration.FRAGMENT_RESOURCES+".cache";
60 public static final String CACHED_CONTAINER_RESOURCES = WebInfConfiguration.RESOURCE_DIRS+".cache";
61 public static final String METAINF_TLDS = "org.eclipse.jetty.tlds";
62 public static final String METAINF_FRAGMENTS = FragmentConfiguration.FRAGMENT_RESOURCES;
63 public static final String METAINF_RESOURCES = WebInfConfiguration.RESOURCE_DIRS;
64
65 @Override
66 public void preConfigure(final WebAppContext context) throws Exception
67 {
68 boolean useContainerCache = DEFAULT_USE_CONTAINER_METAINF_CACHE;
69 Boolean attr = (Boolean)context.getServer().getAttribute(USE_CONTAINER_METAINF_CACHE);
70 if (attr != null)
71 useContainerCache = attr.booleanValue();
72
73 if (LOG.isDebugEnabled()) LOG.debug("{} = {}", USE_CONTAINER_METAINF_CACHE, useContainerCache);
74
75
76
77
78 if (context.getAttribute(METAINF_TLDS) == null)
79 context.setAttribute(METAINF_TLDS, new HashSet<URL>());
80 if (context.getAttribute(METAINF_RESOURCES) == null)
81 context.setAttribute(METAINF_RESOURCES, new HashSet<Resource>());
82 if (context.getAttribute(METAINF_FRAGMENTS) == null)
83 context.setAttribute(METAINF_FRAGMENTS, new HashMap<Resource, Resource>());
84
85 scanJars(context, context.getMetaData().getContainerResources(), useContainerCache);
86 scanJars(context, context.getMetaData().getWebInfJars(), false);
87 }
88
89
90
91
92
93
94
95
96
97
98
99 public void scanJars (final WebAppContext context, Collection<Resource> jars, boolean useCaches)
100 throws Exception
101 {
102 ConcurrentHashMap<Resource, Resource> metaInfResourceCache = null;
103 ConcurrentHashMap<Resource, Resource> metaInfFragmentCache = null;
104 ConcurrentHashMap<Resource, Collection<URL>> metaInfTldCache = null;
105 if (useCaches)
106 {
107 metaInfResourceCache = (ConcurrentHashMap<Resource, Resource>)context.getServer().getAttribute(CACHED_CONTAINER_RESOURCES);
108 if (metaInfResourceCache == null)
109 {
110 metaInfResourceCache = new ConcurrentHashMap<Resource,Resource>();
111 context.getServer().setAttribute(CACHED_CONTAINER_RESOURCES, metaInfResourceCache);
112 }
113 metaInfFragmentCache = (ConcurrentHashMap<Resource, Resource>)context.getServer().getAttribute(CACHED_CONTAINER_FRAGMENTS);
114 if (metaInfFragmentCache == null)
115 {
116 metaInfFragmentCache = new ConcurrentHashMap<Resource,Resource>();
117 context.getServer().setAttribute(CACHED_CONTAINER_FRAGMENTS, metaInfFragmentCache);
118 }
119 metaInfTldCache = (ConcurrentHashMap<Resource, Collection<URL>>)context.getServer().getAttribute(CACHED_CONTAINER_TLDS);
120 if (metaInfTldCache == null)
121 {
122 metaInfTldCache = new ConcurrentHashMap<Resource,Collection<URL>>();
123 context.getServer().setAttribute(CACHED_CONTAINER_TLDS, metaInfTldCache);
124 }
125 }
126
127
128 if (jars != null)
129 {
130 for (Resource r : jars)
131 {
132
133 scanForResources(context, r, metaInfResourceCache);
134 scanForFragment(context, r, metaInfFragmentCache);
135 scanForTlds(context, r, metaInfTldCache);
136 }
137 }
138 }
139
140
141
142
143
144
145
146
147
148 public void scanForResources (WebAppContext context, Resource target, ConcurrentHashMap<Resource,Resource> cache)
149 throws Exception
150 {
151 Resource resourcesDir = null;
152 if (cache != null && cache.containsKey(target))
153 {
154 resourcesDir = cache.get(target);
155 if (resourcesDir == EmptyResource.INSTANCE)
156 {
157 if (LOG.isDebugEnabled()) LOG.debug(target+" cached as containing no META-INF/resources");
158 return;
159 }
160 else
161 if (LOG.isDebugEnabled()) LOG.debug(target+" META-INF/resources found in cache ");
162 }
163 else
164 {
165
166 if (LOG.isDebugEnabled()) LOG.debug(target+" META-INF/resources checked");
167 if (target.isDirectory())
168 {
169
170 resourcesDir = target.addPath("/META-INF/resources");
171 }
172 else
173 {
174
175 URI uri = target.getURI();
176 resourcesDir = Resource.newResource("jar:"+uri+"!/META-INF/resources");
177 }
178 if (!resourcesDir.exists() || !resourcesDir.isDirectory())
179 resourcesDir = EmptyResource.INSTANCE;
180
181 if (cache != null)
182 {
183 Resource old = cache.putIfAbsent(target, resourcesDir);
184 if (old != null)
185 resourcesDir = old;
186 else
187 if (LOG.isDebugEnabled()) LOG.debug(target+" META-INF/resources cache updated");
188 }
189
190 if (resourcesDir == EmptyResource.INSTANCE)
191 return;
192 }
193
194
195 Set<Resource> dirs = (Set<Resource>)context.getAttribute(METAINF_RESOURCES);
196 if (dirs == null)
197 {
198 dirs = new HashSet<Resource>();
199 context.setAttribute(METAINF_RESOURCES, dirs);
200 }
201 if (LOG.isDebugEnabled()) LOG.debug(resourcesDir+" added to context");
202 dirs.add(resourcesDir);
203 }
204
205
206
207
208
209
210
211
212
213 public void scanForFragment (WebAppContext context, Resource jar, ConcurrentHashMap<Resource,Resource> cache)
214 throws Exception
215 {
216 Resource webFrag = null;
217 if (cache != null && cache.containsKey(jar))
218 {
219 webFrag = cache.get(jar);
220 if (webFrag == EmptyResource.INSTANCE)
221 {
222 if (LOG.isDebugEnabled()) LOG.debug(jar+" cached as containing no META-INF/web-fragment.xml");
223 return;
224 }
225 else
226 if (LOG.isDebugEnabled()) LOG.debug(jar+" META-INF/web-fragment.xml found in cache ");
227 }
228 else
229 {
230
231 if (LOG.isDebugEnabled()) LOG.debug(jar+" META-INF/web-fragment.xml checked");
232 if (jar.isDirectory())
233 {
234
235 webFrag = jar.addPath("/META-INF/web-fragment.xml");
236 }
237 else
238 {
239 URI uri = jar.getURI();
240 webFrag = Resource.newResource("jar:"+uri+"!/META-INF/web-fragment.xml");
241 }
242 if (!webFrag.exists() || webFrag.isDirectory())
243 webFrag = EmptyResource.INSTANCE;
244
245 if (cache != null)
246 {
247
248 Resource old = cache.putIfAbsent(jar, webFrag);
249 if (old != null)
250 webFrag = old;
251 else
252 if (LOG.isDebugEnabled()) LOG.debug(jar+" META-INF/web-fragment.xml cache updated");
253 }
254
255 if (webFrag == EmptyResource.INSTANCE)
256 return;
257 }
258
259 Map<Resource, Resource> fragments = (Map<Resource,Resource>)context.getAttribute(METAINF_FRAGMENTS);
260 if (fragments == null)
261 {
262 fragments = new HashMap<Resource, Resource>();
263 context.setAttribute(METAINF_FRAGMENTS, fragments);
264 }
265 fragments.put(jar, webFrag);
266 if (LOG.isDebugEnabled()) LOG.debug(webFrag+" added to context");
267 }
268
269
270
271
272
273
274
275
276
277
278 public void scanForTlds (WebAppContext context, Resource jar, ConcurrentHashMap<Resource, Collection<URL>> cache)
279 throws Exception
280 {
281 Collection<URL> tlds = null;
282
283 if (cache != null && cache.containsKey(jar))
284 {
285 Collection<URL> tmp = cache.get(jar);
286 if (tmp.isEmpty())
287 {
288 if (LOG.isDebugEnabled()) LOG.debug(jar+" cached as containing no tlds");
289 return;
290 }
291 else
292 {
293 tlds = tmp;
294 if (LOG.isDebugEnabled()) LOG.debug(jar+" tlds found in cache ");
295 }
296 }
297 else
298 {
299
300 Resource metaInfDir = null;
301 if (jar.isDirectory())
302 {
303
304 metaInfDir = jar.addPath("/META-INF/");
305 }
306 else
307 {
308 URI uri = jar.getURI();
309 metaInfDir = Resource.newResource("jar:"+uri+"!/META-INF/");
310 }
311
312
313 tlds = new HashSet<URL>();
314 Collection<Resource> resources = metaInfDir.getAllResources();
315 for (Resource t:resources)
316 {
317 String name = t.toString();
318 if (name.endsWith(".tld"))
319 {
320 if (LOG.isDebugEnabled()) LOG.debug(t+" tld discovered");
321 tlds.add(t.getURL());
322 }
323 }
324 if (cache != null)
325 {
326 if (LOG.isDebugEnabled()) LOG.debug(jar+" tld cache updated");
327 Collection<URL> old = (Collection<URL>)cache.putIfAbsent(jar, tlds);
328 if (old != null)
329 tlds = old;
330 }
331
332 if (tlds.isEmpty())
333 return;
334 }
335
336 Collection<URL> tld_resources=(Collection<URL>)context.getAttribute(METAINF_TLDS);
337 if (tld_resources == null)
338 {
339 tld_resources = new HashSet<URL>();
340 context.setAttribute(METAINF_TLDS, tld_resources);
341 }
342 tld_resources.addAll(tlds);
343 if (LOG.isDebugEnabled()) LOG.debug("tlds added to context");
344 }
345
346
347 @Override
348 public void postConfigure(WebAppContext context) throws Exception
349 {
350 context.setAttribute(METAINF_FRAGMENTS, null);
351 context.setAttribute(METAINF_RESOURCES, null);
352 context.setAttribute(METAINF_TLDS, null);
353 }
354 }