1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.resource;
20
21 import java.util.logging.Level;
22 import java.util.logging.Logger;
23
24 import javax.faces.application.ProjectStage;
25 import javax.faces.context.ExternalContext;
26 import javax.faces.context.FacesContext;
27
28 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
29 import org.apache.myfaces.shared.util.ConcurrentLRUCache;
30 import org.apache.myfaces.shared.util.WebConfigParamUtils;
31
32 public class ResourceHandlerCache
33 {
34 private static final Logger log = Logger
35 .getLogger(ResourceHandlerCache.class.getName());
36
37 private Boolean _resourceCacheEnabled = null;
38 private volatile ConcurrentLRUCache<Object, ResourceValue> _resourceCacheMap = null;
39
40 private volatile ConcurrentLRUCache<Object, ResourceValue> _viewResourceCacheMap = null;
41
42 private volatile ConcurrentLRUCache<Object, Boolean> _libraryExistsCacheMap = null;
43
44
45
46
47
48
49 @JSFWebConfigParam(defaultValue = "500", since = "2.0.2", group="resources",
50 classType="java.lang.Integer", tags="performance")
51 private static final String RESOURCE_HANDLER_CACHE_SIZE_ATTRIBUTE =
52 "org.apache.myfaces.RESOURCE_HANDLER_CACHE_SIZE";
53 private static final int RESOURCE_HANDLER_CACHE_DEFAULT_SIZE = 500;
54
55
56
57
58
59
60 @JSFWebConfigParam(defaultValue = "true", since = "2.0.2", group="resources",
61 expectedValues="true,false", tags="performance")
62 private static final String RESOURCE_HANDLER_CACHE_ENABLED_ATTRIBUTE =
63 "org.apache.myfaces.RESOURCE_HANDLER_CACHE_ENABLED";
64 private static final boolean RESOURCE_HANDLER_CACHE_ENABLED_DEFAULT = true;
65
66 public ResourceValue getResource(String resourceName, String libraryName,
67 String contentType, String localePrefix)
68 {
69 return getResource(resourceName, libraryName, contentType, localePrefix, null);
70 }
71
72 public ResourceValue getResource(String resourceName, String libraryName,
73 String contentType, String localePrefix, String contractName)
74 {
75 if (!isResourceCachingEnabled() || _resourceCacheMap == null)
76 {
77 return null;
78 }
79
80 if (log.isLoggable(Level.FINE))
81 {
82 log.log(Level.FINE, "Attemping to get resource from cache for "
83 + resourceName);
84 }
85
86 ResourceKey key = new ResourceKey(resourceName, libraryName, contentType, localePrefix, contractName);
87
88 return _resourceCacheMap.get(key);
89 }
90
91 public boolean containsResource(String resourceName, String libraryName, String contentType, String localePrefix)
92 {
93 return containsResource(resourceName, libraryName, contentType, localePrefix, null);
94 }
95
96 public boolean containsResource(String resourceName, String libraryName, String contentType,
97 String localePrefix, String contractName)
98 {
99 if (!isResourceCachingEnabled() || _resourceCacheMap == null)
100 {
101 return false;
102 }
103
104 ResourceKey key = new ResourceKey(resourceName, libraryName, contentType, localePrefix);
105 return _resourceCacheMap.get(key) != null;
106 }
107
108 public void putResource(String resourceName, String libraryName,
109 String contentType, String localePrefix, ResourceMeta resource, ResourceLoader loader)
110 {
111 putResource(resourceName, libraryName, contentType, localePrefix, null, resource, loader, null);
112 }
113
114 public void putResource(String resourceName, String libraryName,
115 String contentType, String localePrefix, String contractName, ResourceMeta resource, ResourceLoader loader,
116 ResourceCachedInfo info)
117 {
118 if (!isResourceCachingEnabled())
119 {
120 return;
121 }
122
123 if (log.isLoggable(Level.FINE))
124 {
125 log.log(Level.FINE, "Attemping to put resource to cache for "
126 + resourceName);
127 }
128
129 if (_resourceCacheMap == null)
130 {
131 if (log.isLoggable(Level.FINE))
132 {
133 log.log(Level.FINE, "Initializing resource cache map");
134 }
135 int maxSize = getMaxSize();
136 _resourceCacheMap = new ConcurrentLRUCache<Object, ResourceValue>(
137 (maxSize * 4 + 3) / 3, maxSize);
138 }
139
140 _resourceCacheMap.put(new ResourceKey(resourceName, libraryName,
141 contentType, localePrefix, contractName), new ResourceValue(resource, loader, info));
142 }
143
144 public ResourceValue getResource(String resourceId)
145 {
146 if (!isResourceCachingEnabled() || _resourceCacheMap == null)
147 {
148 return null;
149 }
150
151 if (log.isLoggable(Level.FINE))
152 {
153 log.log(Level.FINE, "Attemping to get resource from cache for "
154 + resourceId);
155 }
156
157 return _resourceCacheMap.get(resourceId);
158 }
159
160 public ResourceValue getResource(String resourceId, String contractName)
161 {
162 if (!isResourceCachingEnabled() || _resourceCacheMap == null)
163 {
164 return null;
165 }
166
167 if (log.isLoggable(Level.FINE))
168 {
169 log.log(Level.FINE, "Attemping to get resource from cache for "
170 + resourceId);
171 }
172
173 return _resourceCacheMap.get(contractName+':'+resourceId);
174 }
175
176 public boolean containsResource(String resourceId, String contractName)
177 {
178 if (!isResourceCachingEnabled() || _resourceCacheMap == null)
179 {
180 return false;
181 }
182
183 return _resourceCacheMap.get(contractName+':'+resourceId) != null;
184 }
185
186 public boolean containsResource(String resourceId)
187 {
188 if (!isResourceCachingEnabled() || _resourceCacheMap == null)
189 {
190 return false;
191 }
192
193 return _resourceCacheMap.get(resourceId) != null;
194 }
195
196 public void putResource(String resourceId, ResourceMeta resource, ResourceLoader loader,
197 ResourceCachedInfo info)
198 {
199 if (!isResourceCachingEnabled())
200 {
201 return;
202 }
203
204 if (log.isLoggable(Level.FINE))
205 {
206 log.log(Level.FINE, "Attemping to put resource to cache for "
207 + resourceId);
208 }
209
210 if (_resourceCacheMap == null)
211 {
212 if (log.isLoggable(Level.FINE))
213 {
214 log.log(Level.FINE, "Initializing resource cache map");
215 }
216 int maxSize = getMaxSize();
217 _resourceCacheMap = new ConcurrentLRUCache<Object, ResourceValue>(
218 (maxSize * 4 + 3) / 3, maxSize);
219 }
220
221 if (resource.getContractName() != null)
222 {
223 _resourceCacheMap.put(resource.getContractName()+':'+resourceId,
224 new ResourceValue(resource, loader));
225 }
226 else
227 {
228 _resourceCacheMap.put(resourceId, new ResourceValue(resource, loader, info));
229 }
230 }
231
232 public boolean containsViewResource(
233 String resourceName, String contentType, String localePrefix)
234 {
235 return containsViewResource(resourceName, contentType, localePrefix, null);
236 }
237
238 public boolean containsViewResource(String resourceName, String contentType,
239 String localePrefix, String contractName)
240 {
241 if (!isResourceCachingEnabled() || _viewResourceCacheMap == null)
242 {
243 return false;
244 }
245
246 ResourceKey key = new ResourceKey(resourceName, null, contentType, localePrefix, contractName);
247 return _viewResourceCacheMap.get(key) != null;
248 }
249
250 public ResourceValue getViewResource(String resourceName,
251 String contentType, String localePrefix)
252 {
253 return getViewResource(resourceName, contentType, localePrefix, null);
254 }
255
256 public ResourceValue getViewResource(String resourceName,
257 String contentType, String localePrefix, String contractName)
258 {
259 if (!isResourceCachingEnabled() || _viewResourceCacheMap == null)
260 {
261 return null;
262 }
263
264 if (log.isLoggable(Level.FINE))
265 {
266 log.log(Level.FINE, "Attemping to get resource from cache for "
267 + resourceName);
268 }
269
270 ResourceKey key = new ResourceKey(resourceName, null, contentType, localePrefix, contractName);
271
272 return _viewResourceCacheMap.get(key);
273 }
274
275 public void putViewResource(String resourceName, String contentType,
276 String localePrefix, ResourceMeta resource, ResourceLoader loader, ResourceCachedInfo info)
277 {
278 putViewResource(resourceName, contentType, localePrefix, null, resource, loader, info);
279 }
280
281 public void putViewResource(String resourceName, String contentType,
282 String localePrefix, String contractName, ResourceMeta resource, ResourceLoader loader,
283 ResourceCachedInfo info)
284 {
285 if (!isResourceCachingEnabled())
286 {
287 return;
288 }
289
290 if (log.isLoggable(Level.FINE))
291 {
292 log.log(Level.FINE, "Attemping to put resource to cache for "
293 + resourceName);
294 }
295
296 if (_viewResourceCacheMap == null)
297 {
298 if (log.isLoggable(Level.FINE))
299 {
300 log.log(Level.FINE, "Initializing resource cache map");
301 }
302 int maxSize = getMaxSize();
303 _viewResourceCacheMap = new ConcurrentLRUCache<Object, ResourceValue>(
304 (maxSize * 4 + 3) / 3, maxSize);
305 }
306
307 _viewResourceCacheMap.put(new ResourceKey(resourceName, null,
308 contentType, localePrefix, contractName), new ResourceValue(resource, loader, info));
309 }
310
311 public Boolean libraryExists(String libraryName)
312 {
313 if (!isResourceCachingEnabled() || _libraryExistsCacheMap == null)
314 {
315 return null;
316 }
317
318 if (log.isLoggable(Level.FINE))
319 {
320 log.log(Level.FINE, "Attemping to get libraryExists from cache for "
321 + libraryName);
322 }
323
324 return _libraryExistsCacheMap.get(libraryName);
325 }
326
327 public void confirmLibraryExists(String libraryName)
328 {
329 if (!isResourceCachingEnabled())
330 {
331 return;
332 }
333
334 if (log.isLoggable(Level.FINE))
335 {
336 log.log(Level.FINE, "Attemping to set confirmLibraryExists on cache "
337 + libraryName);
338 }
339
340 if (_libraryExistsCacheMap == null)
341 {
342 if (log.isLoggable(Level.FINE))
343 {
344 log.log(Level.FINE, "Initializing resource cache map");
345 }
346 int maxSize = getMaxSize()/10;
347 _libraryExistsCacheMap = new ConcurrentLRUCache<Object, Boolean>(
348 (maxSize * 4 + 3) / 3, maxSize);
349 }
350
351 _libraryExistsCacheMap.put(libraryName, Boolean.TRUE);
352 }
353
354 public void confirmLibraryNotExists(String libraryName)
355 {
356 if (!isResourceCachingEnabled())
357 {
358 return;
359 }
360
361 if (log.isLoggable(Level.FINE))
362 {
363 log.log(Level.FINE, "Attemping to set confirmLibraryExists on cache "
364 + libraryName);
365 }
366
367 if (_libraryExistsCacheMap == null)
368 {
369 if (log.isLoggable(Level.FINE))
370 {
371 log.log(Level.FINE, "Initializing resource cache map");
372 }
373 int maxSize = getMaxSize()/5;
374 _libraryExistsCacheMap = new ConcurrentLRUCache<Object, Boolean>(
375 (maxSize * 4 + 3) / 3, maxSize);
376 }
377
378 _libraryExistsCacheMap.put(libraryName, Boolean.FALSE);
379 }
380
381 private boolean isResourceCachingEnabled()
382 {
383 if (_resourceCacheEnabled == null)
384 {
385 FacesContext facesContext = FacesContext.getCurrentInstance();
386
387
388 if (!facesContext.isProjectStage(ProjectStage.Production))
389 {
390 _resourceCacheEnabled = Boolean.FALSE;
391 return _resourceCacheEnabled;
392 }
393
394 ExternalContext externalContext = facesContext.getExternalContext();
395 if (externalContext == null)
396 {
397 return false;
398 }
399
400
401 _resourceCacheEnabled = WebConfigParamUtils.getBooleanInitParameter(externalContext,
402 ResourceHandlerCache.RESOURCE_HANDLER_CACHE_ENABLED_ATTRIBUTE,
403 ResourceHandlerCache.RESOURCE_HANDLER_CACHE_ENABLED_DEFAULT);
404
405 if (log.isLoggable(Level.FINE))
406 {
407 log.log(Level.FINE, "MyFaces Resource Caching Enabled="
408 + _resourceCacheEnabled);
409 }
410 }
411 return _resourceCacheEnabled;
412 }
413
414 private int getMaxSize()
415 {
416
417 ExternalContext externalContext = FacesContext.getCurrentInstance()
418 .getExternalContext();
419 return WebConfigParamUtils.getIntegerInitParameter(externalContext,
420 RESOURCE_HANDLER_CACHE_SIZE_ATTRIBUTE, RESOURCE_HANDLER_CACHE_DEFAULT_SIZE);
421 }
422
423 public static class ResourceKey
424 {
425 private final String resourceName;
426 private final String libraryName;
427 private final String contentType;
428 private final String localePrefix;
429 private final String contractName;
430
431 public ResourceKey(String resourceName, String libraryName,
432 String contentType, String localePrefix)
433 {
434 this(resourceName, libraryName, contentType, localePrefix, null);
435 }
436
437 public ResourceKey(String resourceName, String libraryName,
438 String contentType, String localePrefix, String contractName)
439 {
440 this.resourceName = resourceName;
441 this.libraryName = libraryName;
442 this.contentType = contentType;
443 this.localePrefix = localePrefix;
444 this.contractName = contractName;
445 }
446
447 @Override
448 public boolean equals(Object o)
449 {
450 if (this == o)
451 {
452 return true;
453 }
454 if (o == null || getClass() != o.getClass())
455 {
456 return false;
457 }
458
459 ResourceKey that = (ResourceKey) o;
460
461 if (contentType != null ? !contentType.equals(that.contentType) : that.contentType != null)
462 {
463 return false;
464 }
465 if (libraryName != null ? !libraryName.equals(that.libraryName) : that.libraryName != null)
466 {
467 return false;
468 }
469 if (localePrefix != null ? !localePrefix.equals(that.localePrefix) : that.localePrefix != null)
470 {
471 return false;
472 }
473 if (resourceName != null ? !resourceName.equals(that.resourceName) : that.resourceName != null)
474 {
475 return false;
476 }
477 if (contractName != null ? !contractName.equals(that.contractName) : that.contractName != null)
478 {
479 return false;
480 }
481
482 return true;
483 }
484
485 @Override
486 public int hashCode()
487 {
488 int result = resourceName != null ? resourceName.hashCode() : 0;
489 result = 31 * result + (libraryName != null ? libraryName.hashCode() : 0);
490 result = 31 * result + (contentType != null ? contentType.hashCode() : 0);
491 result = 31 * result + (localePrefix != null ? localePrefix.hashCode() : 0);
492 result = 31 * result + (contractName != null ? contractName.hashCode() : 0);
493 return result;
494 }
495 }
496
497 public static class ResourceValue
498 {
499 private final ResourceMeta resourceMeta;
500
501 private final ResourceLoader resourceLoader;
502
503 private final ResourceCachedInfo info;
504
505 public ResourceValue(ResourceMeta resourceMeta,
506 ResourceLoader resourceLoader)
507 {
508 this.resourceMeta = resourceMeta;
509 this.resourceLoader = resourceLoader;
510 this.info = null;
511 }
512
513 public ResourceValue(ResourceMeta resourceMeta,
514 ResourceLoader resourceLoader,
515 ResourceCachedInfo info)
516 {
517 super();
518 this.resourceMeta = resourceMeta;
519 this.resourceLoader = resourceLoader;
520 this.info = info;
521 }
522
523 public ResourceMeta getResourceMeta()
524 {
525 return resourceMeta;
526 }
527
528 public ResourceLoader getResourceLoader()
529 {
530 return resourceLoader;
531 }
532
533 public ResourceCachedInfo getCachedInfo()
534 {
535 return info;
536 }
537 }
538
539 }