1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.view.facelets.impl;
20
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.net.URL;
24 import java.net.URLConnection;
25 import java.util.HashMap;
26 import java.util.Map;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29 import java.util.regex.Pattern;
30
31 import javax.el.ELException;
32 import javax.faces.FacesException;
33 import javax.faces.FactoryFinder;
34 import javax.faces.application.ViewResource;
35 import javax.faces.context.FacesContext;
36 import javax.faces.view.facelets.Facelet;
37 import javax.faces.view.facelets.FaceletCache;
38 import javax.faces.view.facelets.FaceletCacheFactory;
39 import javax.faces.view.facelets.FaceletContext;
40 import javax.faces.view.facelets.FaceletException;
41 import javax.faces.view.facelets.FaceletHandler;
42 import javax.faces.view.facelets.ResourceResolver;
43
44 import org.apache.myfaces.shared.resource.ResourceLoaderUtils;
45 import org.apache.myfaces.view.facelets.AbstractFaceletCache;
46 import org.apache.myfaces.view.facelets.FaceletFactory;
47 import org.apache.myfaces.view.facelets.compiler.Compiler;
48 import org.apache.myfaces.view.facelets.util.ParameterCheck;
49
50
51
52
53
54
55
56 public final class DefaultFaceletFactory extends FaceletFactory
57 {
58 private static final long INFINITE_DELAY = -1;
59 private static final long NO_CACHE_DELAY = 0;
60
61
62 protected final Logger log = Logger.getLogger(DefaultFaceletFactory.class.getName());
63
64 private URL _baseUrl;
65
66 private Compiler _compiler;
67
68
69
70
71
72 private Map<String, DefaultFacelet> _compositeComponentMetadataFacelets;
73
74 private long _refreshPeriod;
75
76 private Map<String, URL> _relativeLocations;
77
78 private javax.faces.view.facelets.ResourceResolver _resolver;
79 private DefaultResourceResolver _defaultResolver;
80
81 private FaceletCache<Facelet> _faceletCache;
82 private AbstractFaceletCache<Facelet> _abstractFaceletCache;
83
84 public DefaultFaceletFactory(Compiler compiler, ResourceResolver resolver) throws IOException
85 {
86 this(compiler, resolver, -1);
87 }
88
89 public DefaultFaceletFactory(Compiler compiler, ResourceResolver resolver, long refreshPeriod)
90 {
91 ParameterCheck.notNull("compiler", compiler);
92 ParameterCheck.notNull("resolver", resolver);
93
94 _compiler = compiler;
95
96
97
98
99
100 _compositeComponentMetadataFacelets = new HashMap<String, DefaultFacelet>();
101
102 _relativeLocations = new HashMap<String, URL>();
103
104 _resolver = resolver;
105 if (_resolver instanceof DefaultResourceResolver)
106 {
107 _defaultResolver = (DefaultResourceResolver) _resolver;
108 }
109
110
111
112 _refreshPeriod = refreshPeriod < 0 ? INFINITE_DELAY : refreshPeriod * 1000;
113
114
115 FaceletCacheFactory cacheFactory
116 = (FaceletCacheFactory) FactoryFinder.getFactory(FactoryFinder.FACELET_CACHE_FACTORY);
117 _faceletCache = (FaceletCache<Facelet>) cacheFactory.getFaceletCache();
118
119 FaceletCache.MemberFactory<Facelet> faceletFactory = new FaceletCache.MemberFactory<Facelet>()
120 {
121 public Facelet newInstance(URL url) throws IOException
122 {
123 return _createFacelet(url);
124 }
125 };
126 FaceletCache.MemberFactory<Facelet> viewMetadataFaceletFactory = new FaceletCache.MemberFactory<Facelet>()
127 {
128 public Facelet newInstance(URL url) throws IOException
129 {
130 return _createViewMetadataFacelet(url);
131 }
132 };
133
134 if (_faceletCache instanceof AbstractFaceletCache)
135 {
136 _abstractFaceletCache = (AbstractFaceletCache<Facelet>) _faceletCache;
137
138 FaceletCache.MemberFactory<Facelet> compositeComponentMetadataFaceletFactory =
139 new FaceletCache.MemberFactory<Facelet>()
140 {
141 public Facelet newInstance(URL url) throws IOException
142 {
143 return _createCompositeComponentMetadataFacelet(url);
144 }
145 };
146
147 try
148 {
149 _abstractFaceletCache.setCacheFactories(faceletFactory,
150 viewMetadataFaceletFactory, compositeComponentMetadataFaceletFactory);
151 }
152 catch (Exception e)
153 {
154 throw new FacesException(
155 "Cannot call setMemberFactories method, Initialization of FaceletCache failed.",
156 e);
157 }
158 }
159 else
160 {
161
162
163
164
165
166 try
167 {
168 _faceletCache.setCacheFactories(faceletFactory, viewMetadataFaceletFactory);
169 }
170 catch (Exception e)
171 {
172 throw new FacesException(
173 "Cannot call setMemberFactories method, Initialization of FaceletCache failed.",
174 e);
175 }
176 }
177
178 if (log.isLoggable(Level.FINE))
179 {
180 log.fine("Using ResourceResolver: " + _resolver);
181 log.fine("Using Refresh Period: " + _refreshPeriod);
182 }
183 }
184
185
186
187
188
189
190 public Compiler getCompiler()
191 {
192 return _compiler;
193 }
194
195 private URL getBaseUrl()
196 {
197 if (_baseUrl == null)
198 {
199 _baseUrl = _resolver.resolveUrl("/");
200 }
201 return _baseUrl;
202 }
203
204
205
206
207
208
209 @Override
210 public Facelet getFacelet(FacesContext facesContext, String uri)
211 throws IOException, FaceletException, FacesException, ELException
212 {
213 URL url = (URL) _relativeLocations.get(uri);
214 if (url == null)
215 {
216 url = resolveURL(facesContext, getBaseUrl(), uri);
217 if (url != null)
218 {
219 ViewResource viewResource = (ViewResource) facesContext.getAttributes().get(
220 FaceletFactory.LAST_RESOURCE_RESOLVED);
221 if (viewResource != null)
222 {
223
224
225 }
226 else
227 {
228 Map<String, URL> newLoc = new HashMap<String, URL>(_relativeLocations);
229 newLoc.put(uri, url);
230 _relativeLocations = newLoc;
231 }
232 }
233 else
234 {
235 throw new IOException("'" + uri + "' not found.");
236 }
237 }
238 return this.getFacelet(url);
239 }
240
241
242
243
244
245
246
247
248
249
250
251
252
253 @Override
254 public Facelet getFacelet(URL url) throws IOException, FaceletException, FacesException, ELException
255 {
256 return _faceletCache.getFacelet(url);
257 }
258
259
260 @Override
261 public Facelet getFacelet(FaceletContext ctx, URL url)
262 throws IOException, FaceletException, FacesException, ELException
263 {
264 if (_abstractFaceletCache != null)
265 {
266 return _abstractFaceletCache.getFacelet(ctx, url);
267 }
268 else
269 {
270 return _faceletCache.getFacelet(url);
271 }
272 }
273
274 public long getRefreshPeriod()
275 {
276 return _refreshPeriod;
277 }
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292 public URL resolveURL(FacesContext context, URL source, String path) throws IOException
293 {
294 if (path.startsWith("/"))
295 {
296 context.getAttributes().put(LAST_RESOURCE_RESOLVED, null);
297 URL url = resolveURL(context, path);
298 if (url == null)
299 {
300 throw new FileNotFoundException(path + " Not Found in ExternalContext as a Resource");
301 }
302 return url;
303 }
304 else
305 {
306 return new URL(source, path);
307 }
308 }
309
310
311
312
313
314
315
316
317 protected boolean needsToBeRefreshed(DefaultFacelet facelet)
318 {
319
320 if (_refreshPeriod == NO_CACHE_DELAY)
321 {
322 return true;
323 }
324
325
326 if (_refreshPeriod == INFINITE_DELAY)
327 {
328 return false;
329 }
330
331 long target = facelet.getCreateTime() + _refreshPeriod;
332 if (System.currentTimeMillis() > target)
333 {
334
335
336 URLConnection conn = null;
337 try
338 {
339 conn = facelet.getSource().openConnection();
340 long lastModified = ResourceLoaderUtils.getResourceLastModified(conn);
341
342 return lastModified == 0 || lastModified > target;
343 }
344 catch (IOException e)
345 {
346 throw new FaceletException("Error Checking Last Modified for " + facelet.getAlias(), e);
347 }
348 finally
349 {
350 if (conn != null)
351 {
352 try
353 {
354 conn.getInputStream().close();
355 }
356 catch (Exception e)
357 {
358
359 }
360 }
361 }
362 }
363
364 return false;
365 }
366
367
368
369
370
371
372
373
374
375
376
377
378 private DefaultFacelet _createFacelet(URL url) throws IOException, FaceletException, FacesException, ELException
379 {
380 if (log.isLoggable(Level.FINE))
381 {
382 log.fine("Creating Facelet for: " + url);
383 }
384
385 String alias = "/" + _removeFirst(url.getFile(), getBaseUrl().getFile());
386 try
387 {
388 FaceletHandler h = _compiler.compile(url, alias);
389 DefaultFacelet f = new DefaultFacelet(this, _compiler.createExpressionFactory(), url, alias, alias, h);
390 return f;
391 }
392 catch (FileNotFoundException fnfe)
393 {
394 throw new FileNotFoundException("Facelet " + alias + " not found at: " + url.toExternalForm());
395 }
396 }
397
398
399
400
401
402
403
404
405
406
407 private DefaultFacelet _createViewMetadataFacelet(URL url)
408 throws IOException, FaceletException, FacesException, ELException
409 {
410 if (log.isLoggable(Level.FINE))
411 {
412 log.fine("Creating Facelet used to create View Metadata for: " + url);
413 }
414
415
416
417 String faceletId = "/"+ _removeFirst(url.getFile(), getBaseUrl().getFile());
418 String alias = "/viewMetadata" + faceletId;
419 try
420 {
421 FaceletHandler h = _compiler.compileViewMetadata(url, alias);
422 DefaultFacelet f = new DefaultFacelet(this, _compiler.createExpressionFactory(), url, alias,
423 faceletId, h);
424 return f;
425 }
426 catch (FileNotFoundException fnfe)
427 {
428 throw new FileNotFoundException("Facelet " + alias + " not found at: " + url.toExternalForm());
429 }
430
431 }
432
433
434
435
436
437
438
439
440
441
442 private DefaultFacelet _createCompositeComponentMetadataFacelet(URL url)
443 throws IOException, FaceletException, FacesException, ELException
444 {
445 if (log.isLoggable(Level.FINE))
446 {
447 log.fine("Creating Facelet used to create Composite Component Metadata for: " + url);
448 }
449
450
451
452 String alias = "/compositeComponentMetadata/" + _removeFirst(url.getFile(), getBaseUrl().getFile());
453 try
454 {
455 FaceletHandler h = _compiler.compileCompositeComponentMetadata(url, alias);
456 DefaultFacelet f = new DefaultFacelet(this, _compiler.createExpressionFactory(), url, alias,
457 alias, h, true);
458 return f;
459 }
460 catch (FileNotFoundException fnfe)
461 {
462 throw new FileNotFoundException("Facelet " + alias + " not found at: " + url.toExternalForm());
463 }
464 }
465
466
467
468
469
470
471 @Override
472 public Facelet getViewMetadataFacelet(FacesContext facesContext, String uri)
473 throws IOException
474 {
475 URL url = (URL) _relativeLocations.get(uri);
476 if (url == null)
477 {
478 url = resolveURL(facesContext, getBaseUrl(), uri);
479 ViewResource viewResource = (ViewResource) facesContext.getAttributes().get(
480 FaceletFactory.LAST_RESOURCE_RESOLVED);
481 if (url != null)
482 {
483 if (viewResource != null)
484 {
485
486
487 }
488 else
489 {
490 Map<String, URL> newLoc = new HashMap<String, URL>(_relativeLocations);
491 newLoc.put(uri, url);
492 _relativeLocations = newLoc;
493 }
494 }
495 else
496 {
497 throw new IOException("'" + uri + "' not found.");
498 }
499 }
500 return this.getViewMetadataFacelet(url);
501 }
502
503
504
505
506 @Override
507 public Facelet getViewMetadataFacelet(URL url) throws IOException,
508 FaceletException, FacesException, ELException
509 {
510 if (_abstractFaceletCache != null)
511 {
512 return _abstractFaceletCache.getViewMetadataFacelet(url);
513 }
514 else
515 {
516 return _faceletCache.getViewMetadataFacelet(url);
517 }
518 }
519
520
521
522
523
524
525 @Override
526 public Facelet getCompositeComponentMetadataFacelet(FacesContext facesContext, String uri)
527 throws IOException
528 {
529 URL url = (URL) _relativeLocations.get(uri);
530 if (url == null)
531 {
532 url = resolveURL(facesContext, getBaseUrl(), uri);
533 ViewResource viewResource = (ViewResource) facesContext.getAttributes().get(
534 FaceletFactory.LAST_RESOURCE_RESOLVED);
535 if (url != null)
536 {
537 if (viewResource != null)
538 {
539
540
541 }
542 else
543 {
544 Map<String, URL> newLoc = new HashMap<String, URL>(_relativeLocations);
545 newLoc.put(uri, url);
546 _relativeLocations = newLoc;
547 }
548 }
549 else
550 {
551 throw new IOException("'" + uri + "' not found.");
552 }
553 }
554 return this.getCompositeComponentMetadataFacelet(url);
555 }
556
557
558
559
560 @Override
561 public Facelet getCompositeComponentMetadataFacelet(URL url) throws IOException,
562 FaceletException, FacesException, ELException
563 {
564 if (_abstractFaceletCache != null)
565 {
566 return _abstractFaceletCache.getCompositeComponentMetadataFacelet(url);
567 }
568 else
569 {
570 ParameterCheck.notNull("url", url);
571
572 String key = url.toString();
573
574 DefaultFacelet f = _compositeComponentMetadataFacelets.get(key);
575
576 if (f == null || this.needsToBeRefreshed(f))
577 {
578 f = this._createCompositeComponentMetadataFacelet(url);
579 if (_refreshPeriod != NO_CACHE_DELAY)
580 {
581 Map<String, DefaultFacelet> newLoc
582 = new HashMap<String, DefaultFacelet>(_compositeComponentMetadataFacelets);
583 newLoc.put(key, f);
584 _compositeComponentMetadataFacelets = newLoc;
585 }
586 }
587 return f;
588 }
589 }
590
591 private URL resolveURL(FacesContext context, String path)
592 {
593 if (_defaultResolver != null)
594 {
595 return _defaultResolver.resolveUrl(context, path);
596 }
597 else
598 {
599 return _resolver.resolveUrl(path);
600 }
601 }
602
603 public Facelet compileComponentFacelet(String taglibURI, String tagName, Map<String,Object> attributes)
604 {
605 FaceletHandler handler = _compiler.compileComponent(taglibURI, tagName, attributes);
606 String alias = "/component/oamf:"+tagName;
607 return new DefaultFacelet(this, _compiler.createExpressionFactory(), getBaseUrl(), alias, alias, handler);
608 }
609
610
611
612
613
614
615
616
617
618
619
620 private String _removeFirst(String string, String toRemove)
621 {
622
623
624
625 return Pattern.compile(toRemove, Pattern.LITERAL).matcher(string).replaceFirst("");
626 }
627
628 }