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