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