1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package javax.faces.webapp;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.Stack;
29 import java.util.concurrent.atomic.AtomicInteger;
30 import java.util.logging.Level;
31
32 import javax.faces.component.NamingContainer;
33 import javax.faces.component.UIComponent;
34 import javax.faces.component.UIOutput;
35 import javax.faces.component.UIViewRoot;
36 import javax.faces.context.FacesContext;
37 import javax.faces.render.ResponseStateManager;
38 import javax.servlet.jsp.JspException;
39 import javax.servlet.jsp.JspWriter;
40 import javax.servlet.jsp.PageContext;
41 import javax.servlet.jsp.jstl.core.LoopTag;
42 import javax.servlet.jsp.tagext.BodyContent;
43 import javax.servlet.jsp.tagext.BodyTag;
44 import javax.servlet.jsp.tagext.JspIdConsumer;
45 import javax.servlet.jsp.tagext.Tag;
46
47
48
49
50
51
52
53
54
55
56 public abstract class UIComponentClassicTagBase extends UIComponentTagBase implements BodyTag, JspIdConsumer
57 {
58
59
60 private static final String COMPONENT_STACK_ATTR = "org.apache.myfaces.COMPONENT_STACK";
61
62 private static final String REQUEST_FACES_CONTEXT = "org.apache.myfaces.REQUEST_FACES_CONTEXT";
63
64 private static final String VIEW_IDS = "org.apache.myfaces.VIEW_IDS";
65
66 private static final String FORMER_CHILD_IDS_SET_ATTR = "org.apache.myfaces.FORMER_CHILD_IDS";
67 private static final String FORMER_FACET_NAMES_SET_ATTR = "org.apache.myfaces.FORMER_FACET_NAMES";
68
69 private static final String PREVIOUS_JSP_IDS_SET = "org.apache.myfaces.PREVIOUS_JSP_IDS_SET";
70
71 private static final String BOUND_VIEW_ROOT = "org.apache.myfaces.BOUND_VIEW_ROOT";
72
73 private static final String LOGICAL_PAGE_ID = "org.apache.myfaces.LOGICAL_PAGE_ID";
74
75 private static final String LOGICAL_PAGE_COUNTER = "org.apache.myfaces.LOGICAL_PAGE_COUNTER";
76
77 protected static final String UNIQUE_ID_PREFIX = UIViewRoot.UNIQUE_ID_PREFIX + "_";
78
79 protected PageContext pageContext = null;
80 protected BodyContent bodyContent = null;
81
82 private boolean _created = false;
83
84 private String _jspId = null;
85 private String _facesJspId = null;
86
87 private List<String> _childrenAdded = null;
88 private List<String> _facetsAdded = null;
89
90 private UIComponent _componentInstance = null;
91 private String _id = null;
92
93 private boolean isInAnIterator;
94
95
96 private Tag _parent = null;
97
98
99 private UIComponentClassicTagBase _parentClassicTag = null;
100
101 private FacesContext _facesContext = null;
102
103 protected abstract void setProperties(UIComponent component);
104
105 protected abstract UIComponent createComponent(FacesContext context, String newId) throws JspException;
106
107 public void release()
108 {
109 internalRelease();
110
111
112
113 pageContext = null;
114 _parent = null;
115 _jspId = null;
116 _id = null;
117 _facesJspId = null;
118 bodyContent = null;
119 }
120
121
122
123
124
125
126 private void internalRelease()
127 {
128 _facesContext = null;
129 _componentInstance = null;
130 _created = false;
131
132 _childrenAdded = null;
133 _facetsAdded = null;
134 }
135
136
137
138
139 @Override
140 public boolean getCreated()
141 {
142 return _created;
143 }
144
145 protected List<String> getCreatedComponents()
146 {
147 return _childrenAdded;
148 }
149
150
151
152
153
154
155
156 public static UIComponentClassicTagBase getParentUIComponentClassicTagBase(PageContext pageContext)
157 {
158 Stack<UIComponentClassicTagBase> stack = getStack(pageContext);
159
160 int size = stack.size();
161
162 return size > 0 ? stack.get(size - 1) : null;
163 }
164
165
166
167
168
169 public String getJspId()
170 {
171 return _jspId;
172 }
173
174 public void setJspId(String jspId)
175 {
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 Integer logicalPageId = (Integer) pageContext.getAttribute(LOGICAL_PAGE_ID);
210
211 if (logicalPageId != null)
212 {
213 if (logicalPageId.intValue() == 1)
214 {
215
216 _jspId = jspId;
217 }
218 else
219 {
220
221 _jspId = jspId + "pc" + logicalPageId;
222 }
223 }
224 else
225 {
226 Map<Object, Object> attributeMap = getFacesContext().getAttributes();
227 AtomicInteger logicalPageCounter = (AtomicInteger) attributeMap.get(LOGICAL_PAGE_COUNTER);
228
229 if (logicalPageCounter == null)
230 {
231
232 logicalPageCounter = new AtomicInteger(1);
233 logicalPageId = 1;
234 attributeMap.put(LOGICAL_PAGE_COUNTER, logicalPageCounter);
235 pageContext.setAttribute(LOGICAL_PAGE_ID, logicalPageId);
236 }
237 else
238 {
239
240 logicalPageId = logicalPageCounter.incrementAndGet();
241 pageContext.setAttribute(LOGICAL_PAGE_ID, logicalPageId);
242 _jspId = jspId + "pc" + logicalPageId;
243 }
244 }
245 _facesJspId = null;
246 checkIfItIsInAnIterator(_jspId);
247 }
248
249
250
251
252
253
254
255 @Override
256 protected void addChild(UIComponent child)
257 {
258 if (_childrenAdded == null)
259 {
260 _childrenAdded = new ArrayList<String>();
261 }
262
263 _childrenAdded.add(child.getId());
264 }
265
266
267
268
269
270 @Override
271 protected void addFacet(String name)
272 {
273 if (_facetsAdded == null)
274 {
275 _facetsAdded = new ArrayList<String>();
276 }
277
278 _facetsAdded.add(name);
279 }
280
281
282
283
284
285
286 @Override
287 public UIComponent getComponentInstance()
288 {
289 return _componentInstance;
290 }
291
292
293
294
295
296
297 @Override
298 protected FacesContext getFacesContext()
299 {
300 if (_facesContext != null)
301 {
302 return _facesContext;
303 }
304
305 _facesContext = pageContext == null ? null : (FacesContext)pageContext.getAttribute(REQUEST_FACES_CONTEXT);
306
307 if (_facesContext != null)
308 {
309 return _facesContext;
310 }
311
312 _facesContext = FacesContext.getCurrentInstance();
313
314 if (_facesContext != null)
315 {
316 if (pageContext != null)
317 {
318 pageContext.setAttribute(REQUEST_FACES_CONTEXT, _facesContext);
319 }
320 return _facesContext;
321 }
322
323
324 throw new RuntimeException("FacesContext not found");
325 }
326
327
328
329
330
331
332 @Override
333 protected int getIndexOfNextChildTag()
334 {
335 if (_childrenAdded == null)
336 {
337 return 0;
338 }
339
340 return _childrenAdded.size();
341 }
342
343
344
345
346
347 @Override
348 public void setId(String id)
349 {
350 if (id != null && id.startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
351 {
352 throw new IllegalArgumentException("Id is non-null and starts with UIViewRoot.UNIQUE_ID_PREFIX: " + id);
353 }
354
355 _id = id;
356 }
357
358
359
360
361 protected String getId()
362 {
363 return _id;
364 }
365
366 protected String getFacesJspId()
367 {
368 if (_facesJspId == null)
369 {
370 if (_jspId != null)
371 {
372 _facesJspId = UNIQUE_ID_PREFIX + _jspId;
373
374 if (isIdDuplicated(_facesJspId))
375 {
376 _facesJspId = createNextId(_facesJspId);
377 }
378 }
379 else
380 {
381 _facesJspId = _facesContext.getViewRoot().createUniqueId();
382 }
383 }
384
385 return _facesJspId;
386 }
387
388 public void setBodyContent(BodyContent bodyContent)
389 {
390 this.bodyContent = bodyContent;
391 }
392
393 public void doInitBody() throws JspException
394 {
395
396 }
397
398 @SuppressWarnings("unchecked")
399 public int doAfterBody() throws JspException
400 {
401 UIComponentClassicTagBase parentTag = getParentUIComponentClassicTagBase(pageContext);
402
403 if (isRootTag(parentTag) || isInRenderedChildrenComponent(parentTag))
404 {
405 UIComponent verbatimComp = createVerbatimComponentFromBodyContent();
406
407 if (verbatimComp != null)
408 {
409 List<String> childrenAddedIds =
410 (List<String>)_componentInstance.getAttributes().get(FORMER_CHILD_IDS_SET_ATTR);
411
412 if (childrenAddedIds == null)
413 {
414 _componentInstance.getChildren().add(verbatimComp);
415 }
416 else
417 {
418 int index = _componentInstance.getChildCount();
419 if (childrenAddedIds.size() == index)
420 {
421
422 _componentInstance.getChildren().add(index - 1, verbatimComp);
423 }
424 else
425 {
426 _componentInstance.getChildren().add(verbatimComp);
427 }
428 }
429
430
431 if (parentTag != null)
432 {
433 parentTag.addChild(verbatimComp);
434 }
435 }
436 }
437
438 return getDoAfterBodyValue();
439 }
440
441
442
443
444
445 public void setPageContext(PageContext pageContext)
446 {
447 this.pageContext = pageContext;
448 }
449
450
451
452
453 public Tag getParent()
454 {
455 return _parent;
456 }
457
458
459
460
461 public void setParent(Tag tag)
462 {
463 this._parent = tag;
464 }
465
466 public BodyContent getBodyContent()
467 {
468 return bodyContent;
469 }
470
471 public int doStartTag() throws JspException
472 {
473 this._facesContext = getFacesContext();
474
475 if (_facesContext == null)
476 {
477 throw new JspException("FacesContext not found");
478 }
479
480 _childrenAdded = null;
481 _facetsAdded = null;
482
483 _parentClassicTag = getParentUIComponentClassicTagBase(pageContext);
484
485 UIComponent verbatimComp = null;
486
487
488
489 if (!isFacet())
490 {
491 Tag parent = getParent();
492
493
494 if (parent != null && parent instanceof LoopTag)
495 {
496 JspWriter outWriter = pageContext.getOut();
497 boolean insideJspTag = (outWriter instanceof BodyContent);
498
499 if (!insideJspTag)
500 {
501 try
502 {
503 outWriter.flush();
504 }
505 catch (IOException e)
506 {
507 throw new JspException("Exception flushing when creating verbatim _componentInstance", e);
508 }
509 }
510 }
511
512
513 if (_parentClassicTag != null)
514 {
515 verbatimComp = _parentClassicTag.createVerbatimComponentFromBodyContent();
516 }
517 }
518
519
520 _componentInstance = findComponent(_facesContext);
521
522
523 if (verbatimComp != null && _parentClassicTag != null)
524 {
525 addVerbatimBeforeComponent(_parentClassicTag, verbatimComp, _componentInstance);
526 }
527
528 Map<String, Object> viewComponentIds = getViewComponentIds();
529
530
531
532 Object tagInstance = null;
533 String clientId = null;
534 if (_id != null)
535 {
536 clientId = _componentInstance.getClientId(_facesContext);
537 tagInstance = (viewComponentIds.get(clientId) == this) ? this : null;
538 }
539
540 if (tagInstance == null)
541 {
542
543 if (_id != null)
544 {
545 if (clientId != null)
546 {
547 if (viewComponentIds.containsKey(clientId))
548 {
549 throw new JspException("Duplicated component Id: '" + clientId + "' " + "for component: '"
550 + getPathToComponent(_componentInstance) + "'.");
551 }
552
553 viewComponentIds.put(clientId, this);
554 }
555 }
556
557
558 if (_parentClassicTag != null)
559 {
560 if (isFacet())
561 {
562 _parentClassicTag.addFacet(getFacetName());
563 }
564 else
565 {
566 _parentClassicTag.addChild(_componentInstance);
567 }
568 }
569 }
570
571
572 pushTag();
573
574 return getDoStartValue();
575 }
576
577 public int doEndTag() throws JspException
578 {
579 popTag();
580 UIComponent component = getComponentInstance();
581
582 removeFormerChildren(component);
583 removeFormerFacets(component);
584
585 try
586 {
587 UIComponentClassicTagBase parentTag = getParentUIComponentClassicTagBase(pageContext);
588
589 UIComponent verbatimComp = createVerbatimComponentFromBodyContent();
590
591 if (verbatimComp != null)
592 {
593 component.getChildren().add(verbatimComp);
594
595 if (parentTag != null)
596 {
597 parentTag.addChild(verbatimComp);
598 }
599 }
600 }
601 catch (Throwable e)
602 {
603 throw new JspException(e);
604 }
605 finally
606 {
607 component = null;
608 }
609
610 int retValue = getDoEndValue();
611
612 internalRelease();
613
614 return retValue;
615 }
616
617
618
619
620 protected int getDoAfterBodyValue() throws JspException
621 {
622 return SKIP_BODY;
623 }
624
625
626
627
628
629
630
631
632
633 protected int getDoStartValue() throws JspException
634 {
635 return BodyTag.EVAL_BODY_BUFFERED;
636 }
637
638
639
640
641
642
643
644
645
646 protected int getDoEndValue() throws JspException
647 {
648 return Tag.EVAL_PAGE;
649 }
650
651 protected String getFacetName()
652 {
653 return isFacet() ? ((FacetTag)_parent).getName() : null;
654 }
655
656
657
658
659 protected UIComponent createVerbatimComponentFromBodyContent()
660 {
661 UIOutput verbatimComp = null;
662
663 if (bodyContent != null)
664 {
665 String strContent = bodyContent.getString();
666
667 if (strContent != null)
668 {
669 String trimmedContent = strContent.trim();
670 if (trimmedContent.length() > 0 && !isComment(strContent))
671 {
672 verbatimComp = createVerbatimComponent();
673 verbatimComp.setValue(strContent);
674 }
675 }
676
677 bodyContent.clearBody();
678 }
679
680 return verbatimComp;
681 }
682
683 private static boolean isComment(String bodyContent)
684 {
685 return (bodyContent.startsWith("<!--") && bodyContent.endsWith("-->"));
686 }
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709 protected UIOutput createVerbatimComponent()
710 {
711 UIOutput verbatimComp =
712 (UIOutput)getFacesContext().getApplication().createComponent("javax.faces.HtmlOutputText");
713 verbatimComp.setTransient(true);
714 verbatimComp.getAttributes().put("escape", Boolean.FALSE);
715 verbatimComp.setId(getFacesContext().getViewRoot().createUniqueId());
716
717 return verbatimComp;
718 }
719
720 @SuppressWarnings("unchecked")
721 protected void addVerbatimBeforeComponent(UIComponentClassicTagBase parentTag, UIComponent verbatimComp,
722 UIComponent component)
723 {
724 UIComponent parent = component.getParent();
725
726 if (parent == null)
727 {
728 return;
729 }
730
731 List<UIComponent> children = parent.getChildren();
732
733
734
735
736
737
738
739
740
741 List<String> childrenAddedIds = (List<String>)parent.getAttributes().get(FORMER_CHILD_IDS_SET_ATTR);
742
743 int parentIndex = children.indexOf(component);
744
745 if (childrenAddedIds != null)
746 {
747 if (parentIndex > 0 && childrenAddedIds.size() == parentIndex)
748 {
749 UIComponent formerVerbatim = children.get(parentIndex - 1);
750
751 if (formerVerbatim instanceof UIOutput && formerVerbatim.isTransient())
752 {
753 children.set(parentIndex - 1, verbatimComp);
754 }
755 }
756 }
757
758 children.add(parentIndex, verbatimComp);
759
760 parentTag.addChild(verbatimComp);
761 }
762
763
764
765
766
767
768
769
770 protected void addVerbatimAfterComponent(UIComponentClassicTagBase parentTag, UIComponent verbatim,
771 UIComponent component)
772 {
773 int indexOfComponentInParent = 0;
774 UIComponent parent = component.getParent();
775
776
777
778
779
780 if (null == parent)
781 {
782 return;
783 }
784 List<UIComponent> children = parent.getChildren();
785 indexOfComponentInParent = children.indexOf(component);
786 if (children.size() - 1 == indexOfComponentInParent)
787 {
788 children.add(verbatim);
789 }
790 else
791 {
792 children.add(indexOfComponentInParent + 1, verbatim);
793 }
794 parentTag.addChild(verbatim);
795 }
796
797
798
799
800 protected void setupResponseWriter()
801 {
802 }
803
804
805
806
807
808 protected void encodeBegin() throws IOException
809 {
810 if (log.isLoggable(Level.FINE))
811 {
812 log.fine("Entered encodeBegin for client-Id: " + _componentInstance.getClientId(getFacesContext()));
813 }
814 _componentInstance.encodeBegin(getFacesContext());
815 if (log.isLoggable(Level.FINE))
816 {
817 log.fine("Exited encodeBegin");
818 }
819 }
820
821
822
823
824
825
826 protected void encodeChildren() throws IOException
827 {
828 if (log.isLoggable(Level.FINE))
829 {
830 log.fine("Entered encodeChildren for client-Id: " + _componentInstance.getClientId(getFacesContext()));
831 }
832 _componentInstance.encodeChildren(getFacesContext());
833 if (log.isLoggable(Level.FINE))
834 {
835 log.fine("Exited encodeChildren for client-Id: " + _componentInstance.getClientId(getFacesContext()));
836 }
837 }
838
839
840
841
842
843 protected void encodeEnd() throws IOException
844 {
845 if (log.isLoggable(Level.FINE))
846 {
847 log.fine("Entered encodeEnd for client-Id: " + _componentInstance.getClientId(getFacesContext()));
848 }
849 _componentInstance.encodeEnd(getFacesContext());
850 if (log.isLoggable(Level.FINE))
851 {
852 log.fine("Exited encodeEnd for client-Id: " + _componentInstance.getClientId(getFacesContext()));
853 }
854
855 }
856
857 private boolean isRootTag(UIComponentClassicTagBase parentTag)
858 {
859 return (parentTag == this);
860 }
861
862 private boolean isInRenderedChildrenComponent(UIComponentClassicTagBase tag)
863 {
864 return (_parentClassicTag != null && tag.getComponentInstance().getRendersChildren());
865 }
866
867 private boolean isFacet()
868 {
869 return _parent != null && _parent instanceof FacetTag;
870 }
871
872
873 @SuppressWarnings("unchecked")
874 private Map<String, Object> getViewComponentIds()
875 {
876 Map<Object, Object> attributes = _facesContext.getAttributes();
877 Map<String, Object> viewComponentIds;
878
879 if (_parent == null)
880 {
881
882 viewComponentIds = new HashMap<String, Object>();
883 attributes.put(VIEW_IDS, viewComponentIds);
884 }
885 else
886 {
887 viewComponentIds = (Map<String, Object>) attributes.get(VIEW_IDS);
888
889
890
891 if (viewComponentIds == null)
892 {
893 viewComponentIds = new HashMap<String, Object>();
894 attributes.put(VIEW_IDS, viewComponentIds);
895 }
896 }
897
898 return viewComponentIds;
899 }
900
901 @SuppressWarnings("unchecked")
902 private static final Stack<UIComponentClassicTagBase> getStack(PageContext pageContext)
903 {
904 Stack<UIComponentClassicTagBase> stack =
905 (Stack<UIComponentClassicTagBase>)pageContext.getAttribute(COMPONENT_STACK_ATTR,
906 PageContext.REQUEST_SCOPE);
907
908 if (stack == null)
909 {
910 stack = new Stack<UIComponentClassicTagBase>();
911 pageContext.setAttribute(COMPONENT_STACK_ATTR, stack, PageContext.REQUEST_SCOPE);
912 }
913
914 return stack;
915 }
916
917
918
919
920
921
922 private void popTag()
923 {
924 Stack<UIComponentClassicTagBase> stack = getStack(pageContext);
925
926 int size = stack.size();
927 stack.remove(size - 1);
928 if (size <= 1)
929 {
930 pageContext.removeAttribute(COMPONENT_STACK_ATTR, PageContext.REQUEST_SCOPE);
931 }
932
933 }
934
935 private void pushTag()
936 {
937 getStack(pageContext).add(this);
938 }
939
940
941
942
943
944
945
946 private String getPathToComponent(UIComponent component)
947 {
948 StringBuffer buf = new StringBuffer();
949
950 if (component == null)
951 {
952 buf.append("{Component-Path : ");
953 buf.append("[null]}");
954 return buf.toString();
955 }
956
957 getPathToComponent(component, buf);
958
959 buf.insert(0, "{Component-Path : ");
960 buf.append("}");
961
962 return buf.toString();
963 }
964
965
966 private static void getPathToComponent(UIComponent component, StringBuffer buf)
967 {
968 if (component == null)
969 {
970 return;
971 }
972
973 StringBuffer intBuf = new StringBuffer();
974
975 intBuf.append("[Class: ");
976 intBuf.append(component.getClass().getName());
977 if (component instanceof UIViewRoot)
978 {
979 intBuf.append(",ViewId: ");
980 intBuf.append(((UIViewRoot)component).getViewId());
981 }
982 else
983 {
984 intBuf.append(",Id: ");
985 intBuf.append(component.getId());
986 }
987 intBuf.append("]");
988
989 buf.insert(0, intBuf);
990
991 getPathToComponent(component.getParent(), buf);
992 }
993
994
995
996
997
998
999
1000
1001 @SuppressWarnings("unchecked")
1002 private void removeFormerChildren(UIComponent component)
1003 {
1004 List<String> formerChildIds = (List<String>)component.getAttributes().get(FORMER_CHILD_IDS_SET_ATTR);
1005 if (formerChildIds != null)
1006 {
1007 for (String childId : formerChildIds)
1008 {
1009 if (_childrenAdded == null || !_childrenAdded.contains(childId))
1010 {
1011 UIComponent childToRemove = component.findComponent(childId);
1012 if (childToRemove != null)
1013 {
1014 component.getChildren().remove(childToRemove);
1015 }
1016 }
1017 }
1018 if (_childrenAdded == null)
1019 {
1020 component.getAttributes().remove(FORMER_CHILD_IDS_SET_ATTR);
1021 }
1022 else
1023 {
1024 component.getAttributes().put(FORMER_CHILD_IDS_SET_ATTR, _childrenAdded);
1025 }
1026 }
1027 else
1028 {
1029 if (_childrenAdded != null)
1030 {
1031 component.getAttributes().put(FORMER_CHILD_IDS_SET_ATTR, _childrenAdded);
1032 }
1033 }
1034 }
1035
1036
1037 @SuppressWarnings("unchecked")
1038 private void removeFormerFacets(UIComponent component)
1039 {
1040 List<String> formerFacetNames = (List<String>)component.getAttributes().get(FORMER_FACET_NAMES_SET_ATTR);
1041 if (formerFacetNames != null)
1042 {
1043 for (String facetName : formerFacetNames)
1044 {
1045 if (_facetsAdded == null || !_facetsAdded.contains(facetName))
1046 {
1047 component.getFacets().remove(facetName);
1048 }
1049 }
1050 if (_facetsAdded == null)
1051 {
1052 component.getAttributes().remove(FORMER_FACET_NAMES_SET_ATTR);
1053 }
1054 else
1055 {
1056 component.getAttributes().put(FORMER_FACET_NAMES_SET_ATTR, _facetsAdded);
1057 }
1058 }
1059 else
1060 {
1061 if (_facetsAdded != null)
1062 {
1063 component.getAttributes().put(FORMER_FACET_NAMES_SET_ATTR, _facetsAdded);
1064 }
1065 }
1066 }
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087 protected UIComponent findComponent(FacesContext context) throws JspException
1088 {
1089
1090 if (_componentInstance != null)
1091 {
1092 return _componentInstance;
1093 }
1094
1095
1096
1097
1098 UIComponentClassicTagBase parentTag = getParentUIComponentClassicTagBase(pageContext);
1099
1100 if (parentTag == null)
1101 {
1102
1103 _componentInstance = context.getViewRoot();
1104
1105
1106 Object alreadyBoundViewRootFlag = _componentInstance.getAttributes().get(BOUND_VIEW_ROOT);
1107
1108 if (alreadyBoundViewRootFlag == null)
1109 {
1110 try
1111 {
1112 setProperties(_componentInstance);
1113 }
1114 catch (Throwable e)
1115 {
1116 throw new JspException(e);
1117 }
1118
1119 if (_id != null)
1120 {
1121 _componentInstance.setId(_id);
1122 }
1123 else
1124 {
1125 _componentInstance.setId(getFacesJspId());
1126 }
1127 _componentInstance.getAttributes().put(BOUND_VIEW_ROOT, true);
1128 _created = true;
1129
1130 }
1131 else if (hasBinding())
1132 {
1133 setProperties(_componentInstance);
1134 }
1135
1136 return _componentInstance;
1137 }
1138
1139 UIComponent parent = parentTag.getComponentInstance();
1140
1141 if (parent == null)
1142 {
1143 throw new IllegalStateException("parent is null?");
1144 }
1145
1146 String facetName = getFacetName();
1147 if (facetName != null)
1148 {
1149
1150 String id = createUniqueId(context, parent);
1151 _componentInstance = parent.getFacet(facetName);
1152 if (_componentInstance == null)
1153 {
1154 _componentInstance = createComponent(context, id);
1155 _created = true;
1156 parent.getFacets().put(facetName, _componentInstance);
1157 }
1158 else
1159 {
1160 if (checkFacetNameOnParentExists(parentTag, facetName))
1161 {
1162 throw new IllegalStateException("facet '" + facetName
1163 + "' already has a child associated. current associated _componentInstance id: "
1164 + _componentInstance.getClientId(context) + " class: "
1165 + _componentInstance.getClass().getName());
1166 }
1167 }
1168
1169 addFacetNameToParentTag(parentTag, facetName);
1170 return _componentInstance;
1171 }
1172
1173
1174
1175
1176
1177
1178
1179
1180 String id = createUniqueId(context, parent);
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190 if (parentTag._childrenAdded != null && parentTag._childrenAdded.contains(id))
1191 {
1192 if (log.isLoggable(Level.WARNING))
1193 {
1194 log.warning("There is more than one JSF tag with an id : " + id);
1195 }
1196 }
1197
1198 _componentInstance = findComponent(parent, id);
1199 if (_componentInstance == null)
1200 {
1201 _componentInstance = createComponent(context, id);
1202 if (id.equals(_componentInstance.getId()) )
1203 {
1204 _created = true;
1205 int index = parentTag.getIndexOfNextChildTag();
1206 if (index > parent.getChildCount())
1207 {
1208 index = parent.getChildCount();
1209 }
1210
1211 List<UIComponent> children = parent.getChildren();
1212 children.add(index, _componentInstance);
1213 }
1214
1215
1216
1217
1218
1219 else if (null == findComponent(parent,_componentInstance.getId()))
1220 {
1221 _created = true;
1222 int index = parentTag.getIndexOfNextChildTag();
1223 if (index > parent.getChildCount())
1224 {
1225 index = parent.getChildCount();
1226 }
1227
1228 List<UIComponent> children = parent.getChildren();
1229 children.add(index, _componentInstance);
1230 }
1231 }
1232
1233 return _componentInstance;
1234
1235 }
1236
1237 private UIComponent findComponent(UIComponent parent, String id)
1238 {
1239 for (UIComponent child : parent.getChildren())
1240 {
1241 if (child.getId() != null && child.getId().equals(id))
1242 {
1243 return child;
1244 }
1245 }
1246
1247 return null;
1248 }
1249
1250 private String createUniqueId(FacesContext context, UIComponent parent) throws JspException
1251 {
1252 String id = getId();
1253 if (id == null)
1254 {
1255 id = getFacesJspId();
1256 }
1257 else if (isIdDuplicated(id))
1258 {
1259 if (isInAnIterator)
1260 {
1261 setId(createNextId(id));
1262 id = getId();
1263 }
1264 else
1265 {
1266 if (parent != null)
1267 {
1268
1269 UIComponent namingContainer;
1270
1271 if (parent instanceof NamingContainer)
1272 {
1273 namingContainer = parent;
1274 }
1275 else
1276 {
1277 namingContainer = parent.getParent();
1278 }
1279
1280 if (namingContainer != null)
1281 {
1282 UIComponent component = namingContainer.findComponent(id);
1283
1284 if (component == null || isPostBack(context))
1285 {
1286 return id;
1287 }
1288 }
1289 }
1290
1291 throw new JspException("Duplicated Id found in the view: " + id);
1292 }
1293 }
1294
1295 return id;
1296 }
1297
1298 private String createNextId(String componentId)
1299 {
1300 Integer currentCounter = (Integer) getFacesContext().getAttributes().get(componentId);
1301
1302 int iCurrentCounter = 1;
1303
1304 if (currentCounter != null)
1305 {
1306 iCurrentCounter = currentCounter;
1307 iCurrentCounter++;
1308 }
1309
1310 getFacesContext().getAttributes().put(componentId, iCurrentCounter);
1311
1312
1313
1314
1315
1316
1317
1318 componentId = componentId + UNIQUE_ID_PREFIX + iCurrentCounter;
1319
1320
1321 return componentId;
1322 }
1323
1324 private void checkIfItIsInAnIterator(String jspId)
1325 {
1326 Set<String> previousJspIdsSet = getPreviousJspIdsSet();
1327
1328 if (previousJspIdsSet.contains(jspId))
1329 {
1330 isInAnIterator = true;
1331 }
1332 else
1333 {
1334 previousJspIdsSet.add(jspId);
1335 isInAnIterator = false;
1336 }
1337 }
1338
1339 @SuppressWarnings("unchecked")
1340 private Set<String> getPreviousJspIdsSet()
1341 {
1342 Set<String> previousJspIdsSet =
1343 (Set<String>)getFacesContext().getAttributes().get(PREVIOUS_JSP_IDS_SET);
1344
1345 if (previousJspIdsSet == null)
1346 {
1347 previousJspIdsSet = new HashSet<String>();
1348
1349
1350 getFacesContext().getAttributes().put(PREVIOUS_JSP_IDS_SET, previousJspIdsSet);
1351 }
1352
1353 return previousJspIdsSet;
1354 }
1355
1356 private boolean isIdDuplicated(String componentId)
1357 {
1358 boolean result = false;
1359 if (_parentClassicTag != null)
1360 {
1361 if (_parentClassicTag.isInAnIterator)
1362 {
1363 return true;
1364 }
1365 List<String> childComponents = _parentClassicTag.getCreatedComponents();
1366
1367 if (childComponents != null)
1368 {
1369 result = childComponents.contains(componentId);
1370 if (result && (!isInAnIterator))
1371 {
1372 return true;
1373 }
1374 }
1375 }
1376
1377 return result;
1378 }
1379
1380 private boolean isPostBack(FacesContext facesContext)
1381 {
1382 return facesContext.getExternalContext().getRequestParameterMap().containsKey(
1383 ResponseStateManager.VIEW_STATE_PARAM);
1384 }
1385
1386
1387
1388
1389 private boolean checkFacetNameOnParentExists(UIComponentClassicTagBase parentTag, String facetName)
1390 {
1391 return parentTag._facetsAdded != null && parentTag._facetsAdded.contains(facetName);
1392 }
1393
1394
1395
1396
1397
1398 private void addFacetNameToParentTag(UIComponentClassicTagBase parentTag, String facetName)
1399 {
1400 if (parentTag._facetsAdded == null)
1401 {
1402 parentTag._facetsAdded = new ArrayList<String>();
1403 }
1404 parentTag._facetsAdded.add(facetName);
1405 }
1406
1407 protected abstract boolean hasBinding();
1408
1409 public JspWriter getPreviousOut()
1410 {
1411 return bodyContent.getEnclosingWriter();
1412 }
1413 }