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 log.fine("Entered encodeBegin for client-Id: " + _componentInstance.getClientId(getFacesContext()));
812 _componentInstance.encodeBegin(getFacesContext());
813 if (log.isLoggable(Level.FINE))
814 log.fine("Exited encodeBegin");
815 }
816
817
818
819
820
821
822 protected void encodeChildren() throws IOException
823 {
824 if (log.isLoggable(Level.FINE))
825 log.fine("Entered encodeChildren for client-Id: " + _componentInstance.getClientId(getFacesContext()));
826 _componentInstance.encodeChildren(getFacesContext());
827 if (log.isLoggable(Level.FINE))
828 log.fine("Exited encodeChildren for client-Id: " + _componentInstance.getClientId(getFacesContext()));
829 }
830
831
832
833
834
835 protected void encodeEnd() throws IOException
836 {
837 if (log.isLoggable(Level.FINE))
838 log.fine("Entered encodeEnd for client-Id: " + _componentInstance.getClientId(getFacesContext()));
839 _componentInstance.encodeEnd(getFacesContext());
840 if (log.isLoggable(Level.FINE))
841 log.fine("Exited encodeEnd for client-Id: " + _componentInstance.getClientId(getFacesContext()));
842
843 }
844
845 private boolean isRootTag(UIComponentClassicTagBase parentTag)
846 {
847 return (parentTag == this);
848 }
849
850 private boolean isInRenderedChildrenComponent(UIComponentClassicTagBase tag)
851 {
852 return (_parentClassicTag != null && tag.getComponentInstance().getRendersChildren());
853 }
854
855 private boolean isFacet()
856 {
857 return _parent != null && _parent instanceof FacetTag;
858 }
859
860
861 @SuppressWarnings("unchecked")
862 private Map<String, Object> getViewComponentIds()
863 {
864 Map<Object, Object> attributes = _facesContext.getAttributes();
865 Map<String, Object> viewComponentIds;
866
867 if (_parent == null)
868 {
869
870 viewComponentIds = new HashMap<String, Object>();
871 attributes.put(VIEW_IDS, viewComponentIds);
872 }
873 else
874 {
875 viewComponentIds = (Map<String, Object>) attributes.get(VIEW_IDS);
876
877
878
879 if (viewComponentIds == null)
880 {
881 viewComponentIds = new HashMap<String, Object>();
882 attributes.put(VIEW_IDS, viewComponentIds);
883 }
884 }
885
886 return viewComponentIds;
887 }
888
889 @SuppressWarnings("unchecked")
890 private static final Stack<UIComponentClassicTagBase> getStack(PageContext pageContext)
891 {
892 Stack<UIComponentClassicTagBase> stack =
893 (Stack<UIComponentClassicTagBase>)pageContext.getAttribute(COMPONENT_STACK_ATTR,
894 PageContext.REQUEST_SCOPE);
895
896 if (stack == null)
897 {
898 stack = new Stack<UIComponentClassicTagBase>();
899 pageContext.setAttribute(COMPONENT_STACK_ATTR, stack, PageContext.REQUEST_SCOPE);
900 }
901
902 return stack;
903 }
904
905
906
907
908
909
910 private void popTag()
911 {
912 Stack<UIComponentClassicTagBase> stack = getStack(pageContext);
913
914 int size = stack.size();
915 stack.remove(size - 1);
916 if (size <= 1)
917 pageContext.removeAttribute(COMPONENT_STACK_ATTR, PageContext.REQUEST_SCOPE);
918
919 }
920
921 private void pushTag()
922 {
923 getStack(pageContext).add(this);
924 }
925
926
927
928
929
930
931
932 private String getPathToComponent(UIComponent component)
933 {
934 StringBuffer buf = new StringBuffer();
935
936 if (component == null)
937 {
938 buf.append("{Component-Path : ");
939 buf.append("[null]}");
940 return buf.toString();
941 }
942
943 getPathToComponent(component, buf);
944
945 buf.insert(0, "{Component-Path : ");
946 buf.append("}");
947
948 return buf.toString();
949 }
950
951
952 private static void getPathToComponent(UIComponent component, StringBuffer buf)
953 {
954 if (component == null)
955 return;
956
957 StringBuffer intBuf = new StringBuffer();
958
959 intBuf.append("[Class: ");
960 intBuf.append(component.getClass().getName());
961 if (component instanceof UIViewRoot)
962 {
963 intBuf.append(",ViewId: ");
964 intBuf.append(((UIViewRoot)component).getViewId());
965 }
966 else
967 {
968 intBuf.append(",Id: ");
969 intBuf.append(component.getId());
970 }
971 intBuf.append("]");
972
973 buf.insert(0, intBuf);
974
975 getPathToComponent(component.getParent(), buf);
976 }
977
978
979
980
981
982
983
984
985 @SuppressWarnings("unchecked")
986 private void removeFormerChildren(UIComponent component)
987 {
988 List<String> formerChildIds = (List<String>)component.getAttributes().get(FORMER_CHILD_IDS_SET_ATTR);
989 if (formerChildIds != null)
990 {
991 for (String childId : formerChildIds)
992 {
993 if (_childrenAdded == null || !_childrenAdded.contains(childId))
994 {
995 UIComponent childToRemove = component.findComponent(childId);
996 if (childToRemove != null)
997 {
998 component.getChildren().remove(childToRemove);
999 }
1000 }
1001 }
1002 if (_childrenAdded == null)
1003 {
1004 component.getAttributes().remove(FORMER_CHILD_IDS_SET_ATTR);
1005 }
1006 else
1007 {
1008 component.getAttributes().put(FORMER_CHILD_IDS_SET_ATTR, _childrenAdded);
1009 }
1010 }
1011 else
1012 {
1013 if (_childrenAdded != null)
1014 {
1015 component.getAttributes().put(FORMER_CHILD_IDS_SET_ATTR, _childrenAdded);
1016 }
1017 }
1018 }
1019
1020
1021 @SuppressWarnings("unchecked")
1022 private void removeFormerFacets(UIComponent component)
1023 {
1024 List<String> formerFacetNames = (List<String>)component.getAttributes().get(FORMER_FACET_NAMES_SET_ATTR);
1025 if (formerFacetNames != null)
1026 {
1027 for (String facetName : formerFacetNames)
1028 {
1029 if (_facetsAdded == null || !_facetsAdded.contains(facetName))
1030 {
1031 component.getFacets().remove(facetName);
1032 }
1033 }
1034 if (_facetsAdded == null)
1035 {
1036 component.getAttributes().remove(FORMER_FACET_NAMES_SET_ATTR);
1037 }
1038 else
1039 {
1040 component.getAttributes().put(FORMER_FACET_NAMES_SET_ATTR, _facetsAdded);
1041 }
1042 }
1043 else
1044 {
1045 if (_facetsAdded != null)
1046 {
1047 component.getAttributes().put(FORMER_FACET_NAMES_SET_ATTR, _facetsAdded);
1048 }
1049 }
1050 }
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071 protected UIComponent findComponent(FacesContext context) throws JspException
1072 {
1073
1074 if (_componentInstance != null)
1075 {
1076 return _componentInstance;
1077 }
1078
1079
1080
1081
1082 UIComponentClassicTagBase parentTag = getParentUIComponentClassicTagBase(pageContext);
1083
1084 if (parentTag == null)
1085 {
1086
1087 _componentInstance = context.getViewRoot();
1088
1089
1090 Object alreadyBoundViewRootFlag = _componentInstance.getAttributes().get(BOUND_VIEW_ROOT);
1091
1092 if (alreadyBoundViewRootFlag == null)
1093 {
1094 try
1095 {
1096 setProperties(_componentInstance);
1097 }
1098 catch (Throwable e)
1099 {
1100 throw new JspException(e);
1101 }
1102
1103 if (_id != null)
1104 {
1105 _componentInstance.setId(_id);
1106 }
1107 else
1108 {
1109 _componentInstance.setId(getFacesJspId());
1110 }
1111 _componentInstance.getAttributes().put(BOUND_VIEW_ROOT, true);
1112 _created = true;
1113
1114 }
1115 else if (hasBinding())
1116 {
1117 setProperties(_componentInstance);
1118 }
1119
1120 return _componentInstance;
1121 }
1122
1123 UIComponent parent = parentTag.getComponentInstance();
1124
1125 if (parent == null)
1126 {
1127 throw new IllegalStateException("parent is null?");
1128 }
1129
1130 String facetName = getFacetName();
1131 if (facetName != null)
1132 {
1133
1134 String id = createUniqueId(context, parent);
1135 _componentInstance = parent.getFacet(facetName);
1136 if (_componentInstance == null)
1137 {
1138 _componentInstance = createComponent(context, id);
1139 _created = true;
1140 parent.getFacets().put(facetName, _componentInstance);
1141 }
1142 else
1143 {
1144 if (checkFacetNameOnParentExists(parentTag, facetName))
1145 {
1146 throw new IllegalStateException("facet '" + facetName
1147 + "' already has a child associated. current associated _componentInstance id: "
1148 + _componentInstance.getClientId(context) + " class: "
1149 + _componentInstance.getClass().getName());
1150 }
1151 }
1152
1153 addFacetNameToParentTag(parentTag, facetName);
1154 return _componentInstance;
1155 }
1156
1157
1158
1159
1160
1161
1162
1163
1164 String id = createUniqueId(context, parent);
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174 if (parentTag._childrenAdded != null && parentTag._childrenAdded.contains(id))
1175 {
1176 if (log.isLoggable(Level.WARNING))
1177 log.warning("There is more than one JSF tag with an id : " + id);
1178 }
1179
1180 _componentInstance = findComponent(parent, id);
1181 if (_componentInstance == null)
1182 {
1183 _componentInstance = createComponent(context, id);
1184 if (id.equals(_componentInstance.getId()) )
1185 {
1186 _created = true;
1187 int index = parentTag.getIndexOfNextChildTag();
1188 if (index > parent.getChildCount())
1189 {
1190 index = parent.getChildCount();
1191 }
1192
1193 List<UIComponent> children = parent.getChildren();
1194 children.add(index, _componentInstance);
1195 }
1196
1197
1198
1199
1200
1201 else if (null == findComponent(parent,_componentInstance.getId()))
1202 {
1203 _created = true;
1204 int index = parentTag.getIndexOfNextChildTag();
1205 if (index > parent.getChildCount())
1206 {
1207 index = parent.getChildCount();
1208 }
1209
1210 List<UIComponent> children = parent.getChildren();
1211 children.add(index, _componentInstance);
1212 }
1213 }
1214
1215 return _componentInstance;
1216
1217 }
1218
1219 private UIComponent findComponent(UIComponent parent, String id)
1220 {
1221 for (UIComponent child : parent.getChildren())
1222 {
1223 if (child.getId() != null && child.getId().equals(id))
1224 {
1225 return child;
1226 }
1227 }
1228
1229 return null;
1230 }
1231
1232 private String createUniqueId(FacesContext context, UIComponent parent) throws JspException
1233 {
1234 String id = getId();
1235 if (id == null)
1236 {
1237 id = getFacesJspId();
1238 }
1239 else if (isIdDuplicated(id))
1240 {
1241 if (isInAnIterator)
1242 {
1243 setId(createNextId(id));
1244 id = getId();
1245 }
1246 else
1247 {
1248 if (parent != null)
1249 {
1250
1251 UIComponent namingContainer;
1252
1253 if (parent instanceof NamingContainer)
1254 {
1255 namingContainer = parent;
1256 }
1257 else
1258 {
1259 namingContainer = parent.getParent();
1260 }
1261
1262 if (namingContainer != null)
1263 {
1264 UIComponent component = namingContainer.findComponent(id);
1265
1266 if (component == null || isPostBack(context))
1267 {
1268 return id;
1269 }
1270 }
1271 }
1272
1273 throw new JspException("Duplicated Id found in the view: " + id);
1274 }
1275 }
1276
1277 return id;
1278 }
1279
1280 private String createNextId(String componentId)
1281 {
1282 Integer currentCounter = (Integer) getFacesContext().getAttributes().get(componentId);
1283
1284 int iCurrentCounter = 1;
1285
1286 if (currentCounter != null)
1287 {
1288 iCurrentCounter = currentCounter;
1289 iCurrentCounter++;
1290 }
1291
1292 getFacesContext().getAttributes().put(componentId, iCurrentCounter);
1293
1294
1295
1296
1297
1298
1299
1300 componentId = componentId + UNIQUE_ID_PREFIX + iCurrentCounter;
1301
1302
1303 return componentId;
1304 }
1305
1306 private void checkIfItIsInAnIterator(String jspId)
1307 {
1308 Set<String> previousJspIdsSet = getPreviousJspIdsSet();
1309
1310 if (previousJspIdsSet.contains(jspId))
1311 {
1312 isInAnIterator = true;
1313 }
1314 else
1315 {
1316 previousJspIdsSet.add(jspId);
1317 isInAnIterator = false;
1318 }
1319 }
1320
1321 @SuppressWarnings("unchecked")
1322 private Set<String> getPreviousJspIdsSet()
1323 {
1324 Set<String> previousJspIdsSet =
1325 (Set<String>)getFacesContext().getAttributes().get(PREVIOUS_JSP_IDS_SET);
1326
1327 if (previousJspIdsSet == null)
1328 {
1329 previousJspIdsSet = new HashSet<String>();
1330
1331
1332 getFacesContext().getAttributes().put(PREVIOUS_JSP_IDS_SET, previousJspIdsSet);
1333 }
1334
1335 return previousJspIdsSet;
1336 }
1337
1338 private boolean isIdDuplicated(String componentId)
1339 {
1340 boolean result = false;
1341 if (_parentClassicTag != null)
1342 {
1343 if (_parentClassicTag.isInAnIterator)
1344 {
1345 return true;
1346 }
1347 List<String> childComponents = _parentClassicTag.getCreatedComponents();
1348
1349 if (childComponents != null)
1350 {
1351 result = childComponents.contains(componentId);
1352 if (result && (!isInAnIterator))
1353 {
1354 return true;
1355 }
1356 }
1357 }
1358
1359 return result;
1360 }
1361
1362 private boolean isPostBack(FacesContext facesContext)
1363 {
1364 return facesContext.getExternalContext().getRequestParameterMap().containsKey(
1365 ResponseStateManager.VIEW_STATE_PARAM);
1366 }
1367
1368
1369
1370
1371 private boolean checkFacetNameOnParentExists(UIComponentClassicTagBase parentTag, String facetName)
1372 {
1373 return parentTag._facetsAdded != null && parentTag._facetsAdded.contains(facetName);
1374 }
1375
1376
1377
1378
1379
1380 private void addFacetNameToParentTag(UIComponentClassicTagBase parentTag, String facetName)
1381 {
1382 if (parentTag._facetsAdded == null)
1383 {
1384 parentTag._facetsAdded = new ArrayList<String>();
1385 }
1386 parentTag._facetsAdded.add(facetName);
1387 }
1388
1389 protected abstract boolean hasBinding();
1390
1391 public JspWriter getPreviousOut()
1392 {
1393 return bodyContent.getEnclosingWriter();
1394 }
1395 }