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