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.Externalizable;
22 import java.io.IOException;
23 import java.io.ObjectInput;
24 import java.io.ObjectOutput;
25 import java.net.URL;
26 import java.text.DateFormat;
27 import java.text.SimpleDateFormat;
28 import java.util.Collections;
29 import java.util.Collection;
30 import java.util.Date;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.WeakHashMap;
35 import java.util.logging.Level;
36 import java.util.logging.Logger;
37
38 import javax.el.ELException;
39 import javax.el.ExpressionFactory;
40 import javax.faces.FacesException;
41 import javax.faces.application.Resource;
42 import javax.faces.application.ViewResource;
43 import javax.faces.component.UIComponent;
44 import javax.faces.component.UIViewRoot;
45 import javax.faces.component.UniqueIdVendor;
46 import javax.faces.context.FacesContext;
47 import javax.faces.view.facelets.FaceletContext;
48 import javax.faces.view.facelets.FaceletException;
49 import javax.faces.view.facelets.FaceletHandler;
50 import org.apache.myfaces.shared.config.MyfacesConfig;
51
52 import org.apache.myfaces.view.facelets.AbstractFacelet;
53 import org.apache.myfaces.view.facelets.AbstractFaceletContext;
54 import org.apache.myfaces.view.facelets.FaceletCompositionContext;
55 import org.apache.myfaces.view.facelets.FaceletFactory;
56 import org.apache.myfaces.view.facelets.compiler.EncodingHandler;
57 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
58
59
60
61
62
63
64
65
66 final class DefaultFacelet extends AbstractFacelet
67 {
68 private static final Logger log = Logger.getLogger(DefaultFacelet.class.getName());
69
70 private final static String APPLIED_KEY = "org.apache.myfaces.view.facelets.APPLIED";
71
72 private final String _alias;
73
74 private final String _faceletId;
75
76 private final ExpressionFactory _elFactory;
77
78 private final DefaultFaceletFactory _factory;
79
80 private final long _createTime;
81
82 private final long _refreshPeriod;
83
84 private final Map<String, URL> _relativePaths;
85
86 private final FaceletHandler _root;
87
88 private final URL _src;
89
90 private final boolean _isBuildingCompositeComponentMetadata;
91
92 private final boolean _encodingHandler;
93
94 public DefaultFacelet(DefaultFaceletFactory factory, ExpressionFactory el, URL src, String alias,
95 String faceletId, FaceletHandler root)
96 {
97 _factory = factory;
98 _elFactory = el;
99 _src = src;
100 _root = root;
101 _alias = alias;
102 _faceletId = faceletId;
103 _createTime = System.currentTimeMillis();
104 _refreshPeriod = _factory.getRefreshPeriod();
105 _relativePaths = Collections.synchronizedMap(new WeakHashMap());
106 _isBuildingCompositeComponentMetadata = false;
107 _encodingHandler = (root instanceof EncodingHandler);
108 }
109
110 public DefaultFacelet(DefaultFaceletFactory factory, ExpressionFactory el, URL src, String alias,
111 String faceletId, FaceletHandler root, boolean isBuildingCompositeComponentMetadata)
112 {
113 _factory = factory;
114 _elFactory = el;
115 _src = src;
116 _root = root;
117 _alias = alias;
118 _faceletId = faceletId;
119 _createTime = System.currentTimeMillis();
120 _refreshPeriod = _factory.getRefreshPeriod();
121 _relativePaths = Collections.synchronizedMap(new WeakHashMap());
122 _isBuildingCompositeComponentMetadata = isBuildingCompositeComponentMetadata;
123 _encodingHandler = (root instanceof EncodingHandler);
124 }
125
126
127
128
129
130 public void apply(FacesContext facesContext, UIComponent parent) throws IOException, FacesException,
131 FaceletException, ELException
132 {
133 FaceletCompositionContext myFaceletContext = null;
134 boolean faceletCompositionContextInitialized = false;
135 boolean recordUniqueIds = false;
136 myFaceletContext = FaceletCompositionContext.getCurrentInstance(facesContext);
137 if (myFaceletContext == null)
138 {
139 myFaceletContext = new FaceletCompositionContextImpl(_factory, facesContext);
140 myFaceletContext.init(facesContext);
141 faceletCompositionContextInitialized = true;
142 if (_encodingHandler && !myFaceletContext.isBuildingViewMetadata()
143 && MyfacesConfig.getCurrentInstance(
144 facesContext.getExternalContext()).isViewUniqueIdsCacheEnabled() &&
145 _refreshPeriod <= 0)
146 {
147 List<String> uniqueIdList = ((EncodingHandler)_root).getUniqueIdList();
148 if (uniqueIdList == null)
149 {
150 myFaceletContext.initUniqueIdRecording();
151 recordUniqueIds = true;
152 }
153 else
154 {
155 myFaceletContext.setUniqueIdsIterator(uniqueIdList.iterator());
156 }
157 }
158 if (parent instanceof UIViewRoot)
159 {
160 myFaceletContext.setViewRoot((UIViewRoot)parent);
161 ComponentSupport.setCachedFacesContext((UIViewRoot)parent, facesContext);
162 }
163 }
164 DefaultFaceletContext ctx = new DefaultFaceletContext(facesContext, this, myFaceletContext);
165
166
167
168 FaceletContext oldCtx = (FaceletContext)
169 facesContext.getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, ctx);
170
171 ctx.pushPageContext(new PageContextImpl());
172
173 try
174 {
175
176
177 boolean pushedUniqueIdVendor = false;
178 if (parent instanceof UniqueIdVendor
179 && ctx.getFaceletCompositionContext().getUniqueIdVendorFromStack() == null)
180 {
181 ctx.getFaceletCompositionContext().pushUniqueIdVendorToStack((UniqueIdVendor) parent);
182 pushedUniqueIdVendor = true;
183 }
184
185 this.refresh(parent);
186 myFaceletContext.markForDeletion(parent);
187 _root.apply(ctx, parent);
188 if (faceletCompositionContextInitialized &&
189 parent instanceof UIViewRoot)
190 {
191 UIComponent metadataFacet = parent.getFacet(UIViewRoot.METADATA_FACET_NAME);
192 if (metadataFacet != null)
193 {
194
195
196
197
198 myFaceletContext.removeComponentForDeletion(metadataFacet);
199 }
200 if (myFaceletContext.isRefreshingTransientBuild())
201 {
202 myFaceletContext.finalizeRelocatableResourcesForDeletion((UIViewRoot) parent);
203 }
204 }
205 myFaceletContext.finalizeForDeletion(parent);
206 this.markApplied(parent);
207
208
209 if (pushedUniqueIdVendor)
210 {
211 ctx.getFaceletCompositionContext().popUniqueIdVendorToStack();
212 }
213 }
214 finally
215 {
216 ctx.popPageContext();
217
218 if (faceletCompositionContextInitialized)
219 {
220 if (parent instanceof UIViewRoot)
221 {
222 ComponentSupport.setCachedFacesContext((UIViewRoot)parent, null);
223 }
224 myFaceletContext.release(facesContext);
225 List<String> uniqueIdList = ((EncodingHandler)_root).getUniqueIdList();
226 if (recordUniqueIds && uniqueIdList == null)
227 {
228 uniqueIdList = Collections.unmodifiableList(
229 myFaceletContext.getUniqueIdList());
230 ((EncodingHandler)_root).setUniqueIdList(uniqueIdList);
231 }
232 }
233
234 if (oldCtx != null)
235 {
236 facesContext.getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, oldCtx);
237 }
238 }
239 }
240
241 public void applyDynamicComponentHandler(FacesContext facesContext,
242 UIComponent parent, String baseKey)
243 throws IOException, FacesException, FaceletException, ELException
244 {
245 FaceletCompositionContext fcctx = null;
246 boolean faceletCompositionContextInitialized = false;
247 fcctx = FaceletCompositionContext.getCurrentInstance(facesContext);
248 boolean pushDynCompSection = false;
249 if (fcctx == null)
250 {
251 fcctx = new FaceletCompositionContextImpl(_factory, facesContext,
252 baseKey);
253 fcctx.init(facesContext);
254 faceletCompositionContextInitialized = true;
255 }
256 else
257 {
258 pushDynCompSection = true;
259 fcctx.pushDynamicComponentSection(baseKey);
260 }
261
262
263
264 if (parent.getAttributes().containsKey("oam.vf.DYN_WRAPPER"))
265 {
266 fcctx.setDynamicComponentTopLevel(false);
267 }
268
269 FaceletContext oldCtx = (FaceletContext) facesContext.getAttributes().get(
270 FaceletContext.FACELET_CONTEXT_KEY);
271 DefaultFaceletContext ctx = new DefaultFaceletContext(facesContext, this, fcctx);
272
273
274
275 facesContext.getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, ctx);
276
277 ctx.pushPageContext(new PageContextImpl());
278
279 try
280 {
281
282
283 boolean pushedUniqueIdVendor = false;
284 if (parent instanceof UniqueIdVendor
285 && ctx.getFaceletCompositionContext().getUniqueIdVendorFromStack() == null)
286 {
287 ctx.getFaceletCompositionContext().pushUniqueIdVendorToStack((UniqueIdVendor) parent);
288 pushedUniqueIdVendor = true;
289 }
290
291
292
293 _root.apply(ctx, parent);
294
295
296
297
298 if (pushedUniqueIdVendor)
299 {
300 ctx.getFaceletCompositionContext().popUniqueIdVendorToStack();
301 }
302 }
303 finally
304 {
305 ctx.popPageContext();
306 facesContext.getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, oldCtx);
307
308 if (pushDynCompSection)
309 {
310 fcctx.popDynamicComponentSection();
311 }
312 if (faceletCompositionContextInitialized)
313 {
314 fcctx.release(facesContext);
315 }
316 }
317 }
318
319 private void refresh(UIComponent c)
320 {
321 if (_refreshPeriod > 0)
322 {
323
324
325 int sz = c.getChildCount();
326 if (sz > 0)
327 {
328 UIComponent cc = null;
329 List<UIComponent> cl = c.getChildren();
330 ApplyToken token;
331 while (--sz >= 0)
332 {
333 cc = cl.get(sz);
334 if (!cc.isTransient())
335 {
336 token = (ApplyToken) cc.getAttributes().get(APPLIED_KEY);
337 if (token != null && token._time < _createTime && token._alias.equals(_alias))
338 {
339 if (log.isLoggable(Level.INFO))
340 {
341 DateFormat df = SimpleDateFormat.getTimeInstance();
342 log.info("Facelet[" + _alias + "] was modified @ "
343 + df.format(new Date(_createTime)) + ", flushing component applied @ "
344 + df.format(new Date(token._time)));
345 }
346 cl.remove(sz);
347 }
348 }
349 }
350 }
351
352
353 if (c.getFacetCount() > 0)
354 {
355 Collection<UIComponent> col = c.getFacets().values();
356 UIComponent fc;
357 ApplyToken token;
358 for (Iterator<UIComponent> itr = col.iterator(); itr.hasNext();)
359 {
360 fc = itr.next();
361 if (!fc.isTransient())
362 {
363 token = (ApplyToken) fc.getAttributes().get(APPLIED_KEY);
364 if (token != null && token._time < _createTime && token._alias.equals(_alias))
365 {
366 if (log.isLoggable(Level.INFO))
367 {
368 DateFormat df = SimpleDateFormat.getTimeInstance();
369 log.info("Facelet[" + _alias + "] was modified @ "
370 + df.format(new Date(_createTime)) + ", flushing component applied @ "
371 + df.format(new Date(token._time)));
372 }
373 itr.remove();
374 }
375 }
376 }
377 }
378 }
379 }
380
381 private void markApplied(UIComponent parent)
382 {
383 if (this._refreshPeriod > 0)
384 {
385 int facetCount = parent.getFacetCount();
386 int childCount = parent.getChildCount();
387 if (childCount > 0 || facetCount > 0)
388 {
389 ApplyToken token = new ApplyToken(_alias, System.currentTimeMillis() + _refreshPeriod);
390
391 if (facetCount > 0)
392 {
393 for (UIComponent facet : parent.getFacets().values())
394 {
395 markApplied(token, facet);
396 }
397 }
398 for (int i = 0; i < childCount; i++)
399 {
400 UIComponent child = parent.getChildren().get(i);
401 markApplied(token, child);
402 }
403 }
404 }
405 }
406
407 private void markApplied(ApplyToken token, UIComponent c)
408 {
409 if (!c.isTransient())
410 {
411 Map<String, Object> attr = c.getAttributes();
412 if (!attr.containsKey(APPLIED_KEY))
413 {
414 attr.put(APPLIED_KEY, token);
415 }
416 }
417 }
418
419
420
421
422
423
424 public String getAlias()
425 {
426 return _alias;
427 }
428
429 public String getFaceletId()
430 {
431 return _faceletId;
432 }
433
434
435
436
437
438
439 public ExpressionFactory getExpressionFactory()
440 {
441 return _elFactory;
442 }
443
444
445
446
447
448
449 public long getCreateTime()
450 {
451 return _createTime;
452 }
453
454
455
456
457
458
459
460
461
462
463 private URL getRelativePath(FacesContext facesContext, String path) throws IOException
464 {
465 URL url = (URL) _relativePaths.get(path);
466 if (url == null)
467 {
468 url = _factory.resolveURL(facesContext, _src, path);
469 if (url != null)
470 {
471 ViewResource viewResource = (ViewResource) facesContext.getAttributes().get(
472 FaceletFactory.LAST_RESOURCE_RESOLVED);
473 if (viewResource != null)
474 {
475
476
477 }
478 else
479 {
480 _relativePaths.put(path, url);
481 }
482 }
483 }
484 return url;
485 }
486
487
488
489
490
491
492 public URL getSource()
493 {
494 return _src;
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510 private void include(AbstractFaceletContext ctx, UIComponent parent) throws IOException, FacesException,
511 FaceletException, ELException
512 {
513 ctx.pushPageContext(new PageContextImpl());
514 try
515 {
516 this.refresh(parent);
517 DefaultFaceletContext ctxWrapper = new DefaultFaceletContext((DefaultFaceletContext)ctx, this, false);
518 ctx.getFacesContext().getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, ctxWrapper);
519 _root.apply(ctxWrapper, parent);
520 ctx.getFacesContext().getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, ctx);
521 this.markApplied(parent);
522 }
523 finally
524 {
525 ctx.popPageContext();
526 }
527 }
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547 public void include(AbstractFaceletContext ctx, UIComponent parent, String path)
548 throws IOException, FacesException, FaceletException, ELException
549 {
550 URL url = this.getRelativePath(ctx.getFacesContext(), path);
551 this.include(ctx, parent, url);
552 }
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569 public void include(AbstractFaceletContext ctx, UIComponent parent, URL url) throws IOException, FacesException,
570 FaceletException, ELException
571 {
572 DefaultFacelet f = (DefaultFacelet) _factory.getFacelet(ctx, url);
573 f.include(ctx, parent);
574 }
575
576 public void applyCompositeComponent(AbstractFaceletContext ctx, UIComponent parent, Resource resource)
577 throws IOException, FacesException, FaceletException, ELException
578 {
579
580
581
582
583
584
585 DefaultFacelet f = (DefaultFacelet) _factory.getFacelet(resource.getURL());
586
587 ctx.pushPageContext(new PageContextImpl());
588 try
589 {
590
591
592 boolean pushedUniqueIdVendor = false;
593 FaceletCompositionContext mctx = ctx.getFaceletCompositionContext();
594 if (parent instanceof UniqueIdVendor
595 && ctx.getFaceletCompositionContext().getUniqueIdVendorFromStack() == null)
596 {
597 mctx.pushUniqueIdVendorToStack((UniqueIdVendor) parent);
598 pushedUniqueIdVendor = true;
599 }
600
601 f.refresh(parent);
602 mctx.markForDeletion(parent);
603 DefaultFaceletContext ctxWrapper = new DefaultFaceletContext( (DefaultFaceletContext)ctx, f, true);
604
605
606 ctx.getFacesContext().getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, ctxWrapper);
607 f._root.apply(ctxWrapper, parent);
608 ctx.getFacesContext().getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, ctx);
609 mctx.finalizeForDeletion(parent);
610 f.markApplied(parent);
611
612
613 if (pushedUniqueIdVendor)
614 {
615 ctx.getFaceletCompositionContext().popUniqueIdVendorToStack();
616 }
617 }
618 finally
619 {
620 ctx.popPageContext();
621 }
622 }
623
624 private static class ApplyToken implements Externalizable
625 {
626 public String _alias;
627
628 public long _time;
629
630 public ApplyToken()
631 {
632 }
633
634 public ApplyToken(String alias, long time)
635 {
636 _alias = alias;
637 _time = time;
638 }
639
640 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
641 {
642 _alias = in.readUTF();
643 _time = in.readLong();
644 }
645
646 public void writeExternal(ObjectOutput out) throws IOException
647 {
648 out.writeUTF(_alias);
649 out.writeLong(_time);
650 }
651 }
652
653 public String toString()
654 {
655 return _alias;
656 }
657
658 @Override
659 public boolean isBuildingCompositeComponentMetadata()
660 {
661 return _isBuildingCompositeComponentMetadata;
662 }
663 }