Coverage Report - javax.faces.webapp.UIComponentClassicTagBase
 
Classes in this File Line Coverage Branch Coverage Complexity
UIComponentClassicTagBase
0%
0/419
0%
0/252
3.403
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 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  
  * @since 1.2
 49  
  */
 50  0
 public abstract class UIComponentClassicTagBase extends UIComponentTagBase implements BodyTag, JspIdConsumer
 51  
 {
 52  
 
 53  
     // do not change this w/out doing likewise in UIComponentTag
 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  0
     protected PageContext pageContext = null;
 74  0
     protected BodyContent bodyContent = null;
 75  
 
 76  0
     private boolean _created = false;
 77  
 
 78  0
     private String _jspId = null;
 79  0
     private String _facesJspId = null;
 80  
 
 81  0
     private List<String> _childrenAdded = null;
 82  0
     private List<String> _facetsAdded = null;
 83  
 
 84  0
     private UIComponent _componentInstance = null;
 85  0
     private String _id = null;
 86  
 
 87  
     private boolean isInAnIterator;
 88  
 
 89  
     // the parent tag
 90  0
     private Tag _parent = null;
 91  
 
 92  
     // the enclosing "classic" parent tag
 93  0
     private UIComponentClassicTagBase _parentClassicTag = null;
 94  
 
 95  0
     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  0
         internalRelease();
 104  
 
 105  
         // members, that must/need only be reset when there is no more risk, that the container
 106  
         // wants to reuse this tag
 107  0
         pageContext = null;
 108  0
         _parent = null;
 109  0
         _jspId = null;
 110  0
         _id = null;
 111  0
         _facesJspId = null;
 112  0
         bodyContent = null;
 113  0
     }
 114  
 
 115  
     /**
 116  
      * Reset any members that apply to the according component instance and must not be reused if the container wants to
 117  
      * reuse this tag instance. This method is called when rendering for this tag is finished ( doEndTag() ) or when
 118  
      * released by the container.
 119  
      */
 120  
     private void internalRelease()
 121  
     {
 122  0
         _facesContext = null;
 123  0
         _componentInstance = null;
 124  0
         _created = false;
 125  
 
 126  0
         _childrenAdded = null;
 127  0
         _facetsAdded = null;
 128  0
     }
 129  
 
 130  
     /**
 131  
      * @see http://java.sun.com/javaee/5/docs/api/javax/faces/webapp/UIComponentClassicTagBase.html#getCreated()
 132  
      */
 133  
     @Override
 134  
     public boolean getCreated()
 135  
     {
 136  0
         return _created;
 137  
     }
 138  
 
 139  
     protected List<String> getCreatedComponents()
 140  
     {
 141  0
         return _childrenAdded;
 142  
     }
 143  
 
 144  
     /**
 145  
      * @see http://java.sun.com/javaee/5/docs/api/javax/faces/webapp/UIComponentClassicTagBase.html#
 146  
      *      getParentUIComponentClassicTagBase(javax.servlet.jsp.PageContext)
 147  
      * @param pageContext
 148  
      * @return
 149  
      */
 150  
     public static UIComponentClassicTagBase getParentUIComponentClassicTagBase(PageContext pageContext)
 151  
     {
 152  0
         Stack<UIComponentClassicTagBase> stack = getStack(pageContext);
 153  
 
 154  0
         int size = stack.size();
 155  
 
 156  0
         return size > 0 ? stack.get(size - 1) : null;
 157  
     }
 158  
 
 159  
     /**
 160  
      * @see http://java.sun.com/javaee/5/docs/api/javax/faces/webapp/UIComponentClassicTagBase.html#getFacesJspId()
 161  
      * @return
 162  
      */
 163  
     public String getJspId()
 164  
     {
 165  0
         return _jspId;
 166  
     }
 167  
 
 168  
     public void setJspId(String jspId)
 169  
     {
 170  
         // -= Leonardo Uribe =- The javadoc says the following about this method:
 171  
         //
 172  
         // 1. This method is called by the container before doStartTag(). 
 173  
         // 2. The argument is guaranteed to be unique within the page.
 174  
         //
 175  
         // Doing some tests it was found that the jspId generated in a
 176  
         // jsp:include are "reset", so if before call it it was id10
 177  
         // the tags inside jsp:include starts from id1 (really I suppose a
 178  
         // different counter is used), so if we assign this one
 179  
         // directly it is possible to cause duplicate id exceptions later.
 180  
         //
 181  
         // One problem is caused by f:view tag. This one is not included when
 182  
         // we check for duplicate id, so it is possible to assign to a component
 183  
         // in a jsp:include the id of the UIViewRoot instance and cause a 
 184  
         // duplicate id exception when the view is saved.
 185  
         //
 186  
         // Checking the javadoc it was found the following note:
 187  
         //
 188  
         // "... IMPLEMENTATION NOTE: This method will detect where we are in an 
 189  
         // include and assign a unique ID for each include in a particular 'logical page'. 
 190  
         // This allows us to avoid possible duplicate ID situations for included pages 
 191  
         // that have components without explicit IDs..."
 192  
         //
 193  
         // So we need to keep a counter per logical page or page context found. 
 194  
         // It is assumed the first one should not be suffixed. The others needs to be
 195  
         // suffixed, so all generated ids of those pages are different. The final result
 196  
         // is that jsp:include works correctly.
 197  
         //
 198  
         // Note this implementation detail takes precedence over c:forEach tag. If a
 199  
         // jsp:include is inside a c:forEach, jsp:include takes precedence and the 
 200  
         // iteration prefix is ignored. If a custom id is provided for a component, 
 201  
         // it will throw duplicate id exception, because this code is "override" 
 202  
         // by the custom id, and the iteration suffix only applies on generated ids.
 203  0
         Integer logicalPageId = (Integer) pageContext.getAttribute(LOGICAL_PAGE_ID);
 204  
         
 205  0
         if (logicalPageId != null)
 206  
         {
 207  0
             if (logicalPageId.intValue() == 1)
 208  
             {
 209  
                 //Base case, just pass it unchanged
 210  0
                 _jspId = jspId;
 211  
             }
 212  
             else
 213  
             {
 214  
                 // We are on a different page context, suffix it with the logicalPageId
 215  0
                 _jspId = jspId + "pc" + logicalPageId;
 216  
             }
 217  
         }
 218  
         else
 219  
         {
 220  0
             Map<Object, Object> attributeMap = getFacesContext().getAttributes();
 221  0
             AtomicInteger logicalPageCounter = (AtomicInteger) attributeMap.get(LOGICAL_PAGE_COUNTER);
 222  
             
 223  0
             if (logicalPageCounter == null)
 224  
             {
 225  
                 //We are processing the first component tag. 
 226  0
                 logicalPageCounter = new AtomicInteger(1);
 227  0
                 logicalPageId = 1;
 228  0
                 attributeMap.put(LOGICAL_PAGE_COUNTER, logicalPageCounter);
 229  0
                 pageContext.setAttribute(LOGICAL_PAGE_ID, logicalPageId);
 230  
             }
 231  
             else
 232  
             {
 233  
                 //We are on a different page context, so we need to assign and set.
 234  0
                 logicalPageId = logicalPageCounter.incrementAndGet();
 235  0
                 pageContext.setAttribute(LOGICAL_PAGE_ID, logicalPageId);
 236  0
                 _jspId = jspId + "pc" + logicalPageId;
 237  
             }
 238  
         }
 239  0
         _facesJspId = null;
 240  0
         checkIfItIsInAnIterator(_jspId);
 241  0
     }
 242  
 
 243  
     /**
 244  
      * @param child
 245  
      * @see http://java.sun.com/javaee/5/docs/api/javax/faces/webapp/UIComponentTagBase.html#addChild(javax.faces.
 246  
      *      _componentInstance.UIComponent)
 247  
      */
 248  
 
 249  
     @Override
 250  
     protected void addChild(UIComponent child)
 251  
     {
 252  0
         if (_childrenAdded == null)
 253  
         {
 254  0
             _childrenAdded = new ArrayList<String>();
 255  
         }
 256  
 
 257  0
         _childrenAdded.add(child.getId());
 258  0
     }
 259  
 
 260  
     /**
 261  
      * @param name
 262  
      * @see http://java.sun.com/javaee/5/docs/api/javax/faces/webapp/UIComponentTagBase.html#addFacet(java.lang.String)
 263  
      */
 264  
     @Override
 265  
     protected void addFacet(String name)
 266  
     {
 267  0
         if (_facetsAdded == null)
 268  
         {
 269  0
             _facetsAdded = new ArrayList<String>();
 270  
         }
 271  
 
 272  0
         _facetsAdded.add(name);
 273  0
     }
 274  
 
 275  
     /**
 276  
      * Return the UIComponent instance associated with this tag.
 277  
      * 
 278  
      * @return a UIComponent, never null.
 279  
      */
 280  
     @Override
 281  
     public UIComponent getComponentInstance()
 282  
     {
 283  0
         return _componentInstance;
 284  
     }
 285  
 
 286  
     /**
 287  
      * @return
 288  
      * @see http://java.sun.com/javaee/5/docs/api/javax/faces/webapp/UIComponentTagBase.html#getFacesContext()
 289  
      */
 290  
 
 291  
     @Override
 292  
     protected FacesContext getFacesContext()
 293  
     {
 294  0
         if (_facesContext != null)
 295  
         {
 296  0
             return _facesContext;
 297  
         }
 298  
 
 299  0
         _facesContext = pageContext == null ? null : (FacesContext)pageContext.getAttribute(REQUEST_FACES_CONTEXT);
 300  
 
 301  0
         if (_facesContext != null)
 302  
         {
 303  0
             return _facesContext;
 304  
         }
 305  
 
 306  0
         _facesContext = FacesContext.getCurrentInstance();
 307  
 
 308  0
         if (_facesContext != null)
 309  
         {
 310  0
             if (pageContext != null)
 311  
             {
 312  0
                 pageContext.setAttribute(REQUEST_FACES_CONTEXT, _facesContext);
 313  
             }
 314  0
             return _facesContext;
 315  
         }
 316  
 
 317  
         // should never be reached
 318  0
         throw new RuntimeException("FacesContext not found");
 319  
     }
 320  
 
 321  
     /**
 322  
      * @return
 323  
      * @see http://java.sun.com/javaee/5/docs/api/javax/faces/webapp/UIComponentTagBase.html#getIndexOfNextChildTag()
 324  
      */
 325  
 
 326  
     @Override
 327  
     protected int getIndexOfNextChildTag()
 328  
     {
 329  0
         if (_childrenAdded == null)
 330  
         {
 331  0
             return 0;
 332  
         }
 333  
 
 334  0
         return _childrenAdded.size();
 335  
     }
 336  
 
 337  
     /**
 338  
      * @param id
 339  
      * @see http://java.sun.com/javaee/5/docs/api/javax/faces/webapp/UIComponentTagBase.html#setId(java.lang.String)
 340  
      */
 341  
     @Override
 342  
     public void setId(String id)
 343  
     {
 344  0
         if (id != null && id.startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
 345  
         {
 346  0
             throw new IllegalArgumentException("Id is non-null and starts with UIViewRoot.UNIQUE_ID_PREFIX: " + id);
 347  
         }
 348  
 
 349  0
         _id = id;
 350  0
     }
 351  
 
 352  
     /**
 353  
      * Return the id (if any) specified as an xml attribute on this tag.
 354  
      */
 355  
     protected String getId()
 356  
     {
 357  0
         return _id;
 358  
     }
 359  
 
 360  
     protected String getFacesJspId()
 361  
     {
 362  0
         if (_facesJspId == null)
 363  
         {
 364  0
             if (_jspId != null)
 365  
             {
 366  0
                 _facesJspId = UNIQUE_ID_PREFIX + _jspId;
 367  
 
 368  0
                 if (isIdDuplicated(_facesJspId))
 369  
                 {
 370  0
                     _facesJspId = createNextId(_facesJspId);
 371  
                 }
 372  
             }
 373  
             else
 374  
             {
 375  0
                 _facesJspId = _facesContext.getViewRoot().createUniqueId();
 376  
             }
 377  
         }
 378  
 
 379  0
         return _facesJspId;
 380  
     }
 381  
 
 382  
     public void setBodyContent(BodyContent bodyContent)
 383  
     {
 384  0
         this.bodyContent = bodyContent;
 385  0
     }
 386  
 
 387  
     public void doInitBody() throws JspException
 388  
     {
 389  
         // nothing by default
 390  0
     }
 391  
 
 392  
     @SuppressWarnings("unchecked")
 393  
     public int doAfterBody() throws JspException
 394  
     {
 395  0
         UIComponentClassicTagBase parentTag = getParentUIComponentClassicTagBase(pageContext);
 396  
 
 397  0
         if (isRootTag(parentTag) || isInRenderedChildrenComponent(parentTag))
 398  
         {
 399  0
             UIComponent verbatimComp = createVerbatimComponentFromBodyContent();
 400  
 
 401  0
             if (verbatimComp != null)
 402  
             {
 403  0
                 List<String> childrenAddedIds =
 404  
                         (List<String>)_componentInstance.getAttributes().get(FORMER_CHILD_IDS_SET_ATTR);
 405  
 
 406  0
                 if (childrenAddedIds == null)
 407  
                 {
 408  0
                     _componentInstance.getChildren().add(verbatimComp);
 409  
                 }
 410  
                 else
 411  
                 {
 412  0
                     int index = _componentInstance.getChildCount();
 413  0
                     if (childrenAddedIds.size() == index)
 414  
                     {
 415  
                         // verbatim already present, replace it
 416  0
                         _componentInstance.getChildren().add(index - 1, verbatimComp);
 417  
                     }
 418  
                     else
 419  
                     {
 420  0
                         _componentInstance.getChildren().add(verbatimComp);
 421  
                     }
 422  
                 }
 423  
 
 424  
                 // also tell the parent-tag about the new component instance
 425  0
                 if (parentTag != null)
 426  
                 {
 427  0
                     parentTag.addChild(verbatimComp);
 428  
                 }
 429  
             }
 430  
         }
 431  
 
 432  0
         return getDoAfterBodyValue();
 433  
     }
 434  
 
 435  
     /**
 436  
      * Standard method invoked by the JSP framework to inform this tag of the PageContext associated with the jsp page
 437  
      * currently being processed.
 438  
      */
 439  
     public void setPageContext(PageContext pageContext)
 440  
     {
 441  0
         this.pageContext = pageContext;
 442  0
     }
 443  
 
 444  
     /**
 445  
      * Returns the enclosing JSP tag object. Note that this is not necessarily a JSF tag.
 446  
      */
 447  
     public Tag getParent()
 448  
     {
 449  0
         return _parent;
 450  
     }
 451  
 
 452  
     /**
 453  
      * Standard method invoked by the JSP framework to inform this tag of the enclosing JSP tag object.
 454  
      */
 455  
     public void setParent(Tag tag)
 456  
     {
 457  0
         this._parent = tag;
 458  0
     }
 459  
 
 460  
     public BodyContent getBodyContent()
 461  
     {
 462  0
         return bodyContent;
 463  
     }
 464  
 
 465  
     public int doStartTag() throws JspException
 466  
     {
 467  0
         this._facesContext = getFacesContext();
 468  
 
 469  0
         if (_facesContext == null)
 470  
         {
 471  0
             throw new JspException("FacesContext not found");
 472  
         }
 473  
 
 474  0
         _childrenAdded = null;
 475  0
         _facetsAdded = null;
 476  
 
 477  0
         _parentClassicTag = getParentUIComponentClassicTagBase(pageContext);
 478  
 
 479  0
         UIComponent verbatimComp = null;
 480  
 
 481  
         // create the verbatim component if not inside a facet (facets are rendered
 482  
         // by their parents) and in a component that renders children
 483  0
         if (!isFacet())
 484  
         {
 485  0
             Tag parent = getParent();
 486  
 
 487  
             // flush if in a loop tag and not in a jsp tag
 488  0
             if (parent != null && parent instanceof LoopTag)
 489  
             {
 490  0
                 JspWriter outWriter = pageContext.getOut();
 491  0
                 boolean insideJspTag = (outWriter instanceof BodyContent);
 492  
 
 493  0
                 if (!insideJspTag)
 494  
                 {
 495  
                     try
 496  
                     {
 497  0
                         outWriter.flush();
 498  
                     }
 499  0
                     catch (IOException e)
 500  
                     {
 501  0
                         throw new JspException("Exception flushing when creating verbatim _componentInstance", e);
 502  0
                     }
 503  
                 }
 504  
             }
 505  
 
 506  
             // create the transient _componentInstance
 507  0
             if (_parentClassicTag != null)
 508  
             {
 509  0
                 verbatimComp = _parentClassicTag.createVerbatimComponentFromBodyContent();
 510  
             }
 511  
         }
 512  
 
 513  
         // find the _componentInstance for this tag
 514  0
         _componentInstance = findComponent(_facesContext);
 515  
 
 516  
         // add the verbatim component
 517  0
         if (verbatimComp != null && _parentClassicTag != null)
 518  
         {
 519  0
             addVerbatimBeforeComponent(_parentClassicTag, verbatimComp, _componentInstance);
 520  
         }
 521  
 
 522  0
         Map<String, Object> viewComponentIds = getViewComponentIds();
 523  
 
 524  
         // check that the instance returned by the client ID for the viewComponentIds
 525  
         // is the same like this one, so we do not perform again the check for duplicated ids
 526  0
         Object tagInstance = null;
 527  0
         String clientId = null;
 528  0
         if (_id != null)
 529  
         {
 530  0
             clientId = _componentInstance.getClientId(_facesContext);
 531  0
             tagInstance = (viewComponentIds.get(clientId) == this) ? this : null;
 532  
         }
 533  
 
 534  0
         if (tagInstance == null)
 535  
         {
 536  
             // check for duplicated IDs
 537  0
             if (_id != null)
 538  
             {
 539  0
                 if (clientId != null)
 540  
                 {
 541  0
                     if (viewComponentIds.containsKey(clientId))
 542  
                     {
 543  0
                         throw new JspException("Duplicated component Id: '" + clientId + "' " + "for component: '"
 544  
                                 + getPathToComponent(_componentInstance) + "'.");
 545  
                     }
 546  
 
 547  0
                     viewComponentIds.put(clientId, this);
 548  
                 }
 549  
             }
 550  
 
 551  
             // add to the component or facet to parent
 552  0
             if (_parentClassicTag != null)
 553  
             {
 554  0
                 if (isFacet())
 555  
                 {
 556  0
                     _parentClassicTag.addFacet(getFacetName());
 557  
                 }
 558  
                 else
 559  
                 {
 560  0
                     _parentClassicTag.addChild(_componentInstance);
 561  
                 }
 562  
             }
 563  
         }
 564  
 
 565  
         // push this tag on the stack
 566  0
         pushTag();
 567  
 
 568  0
         return getDoStartValue();
 569  
     }
 570  
 
 571  
     public int doEndTag() throws JspException
 572  
     {
 573  0
         popTag();
 574  0
         UIComponent component = getComponentInstance();
 575  
 
 576  0
         removeFormerChildren(component);
 577  0
         removeFormerFacets(component);
 578  
 
 579  
         try
 580  
         {
 581  0
             UIComponentClassicTagBase parentTag = getParentUIComponentClassicTagBase(pageContext);
 582  
 
 583  0
             UIComponent verbatimComp = createVerbatimComponentFromBodyContent();
 584  
 
 585  0
             if (verbatimComp != null)
 586  
             {
 587  0
                 component.getChildren().add(verbatimComp);
 588  
 
 589  0
                 if (parentTag != null)
 590  
                 {
 591  0
                     parentTag.addChild(verbatimComp);
 592  
                 }
 593  
             }
 594  
         }
 595  0
         catch (Throwable e)
 596  
         {
 597  0
             throw new JspException(e);
 598  
         }
 599  
         finally
 600  
         {
 601  0
             component = null;
 602  0
         }
 603  
 
 604  0
         int retValue = getDoEndValue();
 605  
 
 606  0
         internalRelease();
 607  
 
 608  0
         return retValue;
 609  
     }
 610  
 
 611  
     /**
 612  
      * @throws JspException  
 613  
      */
 614  
     protected int getDoAfterBodyValue() throws JspException
 615  
     {
 616  0
         return SKIP_BODY;
 617  
     }
 618  
 
 619  
     /**
 620  
      * Get the value to be returned by the doStartTag method to the JSP framework. Subclasses which wish to use the
 621  
      * inherited doStartTag but control whether the tag is permitted to contain nested tags or not can just override
 622  
      * this method to return Tag.SOME_CONSTANT.
 623  
      * 
 624  
      * @return BodyTag.EVAL_BODY_BUFFERED
 625  
      * @throws JspException 
 626  
      */
 627  
     protected int getDoStartValue() throws JspException
 628  
     {
 629  0
         return BodyTag.EVAL_BODY_BUFFERED;
 630  
     }
 631  
 
 632  
     /**
 633  
      * Get the value to be returned by the doEndTag method to the JSP framework. Subclasses which wish to use the
 634  
      * inherited doEndTag but control whether the tag is permitted to contain nested tags or not can just override this
 635  
      * method to return Tag.SOME_CONSTANT.
 636  
      * 
 637  
      * @return Tag.EVAL_PAGE
 638  
      * @throws JspException 
 639  
      */
 640  
     protected int getDoEndValue() throws JspException
 641  
     {
 642  0
         return Tag.EVAL_PAGE;
 643  
     }
 644  
 
 645  
     protected String getFacetName()
 646  
     {
 647  0
         return isFacet() ? ((FacetTag)_parent).getName() : null;
 648  
     }
 649  
 
 650  
     /**
 651  
      * Creates a UIComponent from the BodyContent
 652  
      */
 653  
     protected UIComponent createVerbatimComponentFromBodyContent()
 654  
     {
 655  0
         UIOutput verbatimComp = null;
 656  
 
 657  0
         if (bodyContent != null)
 658  
         {
 659  0
             String strContent = bodyContent.getString();
 660  
 
 661  0
             if (strContent != null)
 662  
             {
 663  0
                 String trimmedContent = strContent.trim();
 664  0
                 if (trimmedContent.length() > 0 && !isComment(strContent))
 665  
                 {
 666  0
                     verbatimComp = createVerbatimComponent();
 667  0
                     verbatimComp.setValue(strContent);
 668  
                 }
 669  
             }
 670  
 
 671  0
             bodyContent.clearBody();
 672  
         }
 673  
 
 674  0
         return verbatimComp;
 675  
     }
 676  
 
 677  
     private static boolean isComment(String bodyContent)
 678  
     {
 679  0
         return (bodyContent.startsWith("<!--") && bodyContent.endsWith("-->"));
 680  
     }
 681  
 
 682  
     /**
 683  
      * <p>
 684  
      * Creates a transient UIOutput using the Application, with the following characteristics:
 685  
      * </p>
 686  
      * <p/>
 687  
      * <p>
 688  
      * <code>componentType</code> is <code>javax.faces.HtmlOutputText</code>.
 689  
      * </p>
 690  
      * <p/>
 691  
      * <p>
 692  
      * <code>transient</code> is <code>true</code>.
 693  
      * </p>
 694  
      * <p/>
 695  
      * <p>
 696  
      * <code>escape</code> is <code>false</code>.
 697  
      * </p>
 698  
      * <p/>
 699  
      * <p>
 700  
      * <code>id</code> is <code>FacesContext.getViewRoot().createUniqueId()</code>
 701  
      * </p>
 702  
      */
 703  
     protected UIOutput createVerbatimComponent()
 704  
     {
 705  0
         UIOutput verbatimComp =
 706  
                 (UIOutput)getFacesContext().getApplication().createComponent("javax.faces.HtmlOutputText");
 707  0
         verbatimComp.setTransient(true);
 708  0
         verbatimComp.getAttributes().put("escape", Boolean.FALSE);
 709  0
         verbatimComp.setId(getFacesContext().getViewRoot().createUniqueId());
 710  
 
 711  0
         return verbatimComp;
 712  
     }
 713  
 
 714  
     @SuppressWarnings("unchecked")
 715  
     protected void addVerbatimBeforeComponent(UIComponentClassicTagBase parentTag, UIComponent verbatimComp,
 716  
                                               UIComponent component)
 717  
     {
 718  0
         UIComponent parent = component.getParent();
 719  
 
 720  0
         if (parent == null)
 721  
         {
 722  0
             return;
 723  
         }
 724  
 
 725  0
         List<UIComponent> children = parent.getChildren();
 726  
         // EDGE CASE:
 727  
         // Consider CASE 1 or 2 where the _componentInstance is provided via a
 728  
         // _componentInstance binding in session or application scope.
 729  
         // The automatically created UIOuput instances for the template text
 730  
         // will already be present. Check the JSP_CREATED_COMPONENT_IDS attribute,
 731  
         // if present and the number of created components is the same
 732  
         // as the number of children replace at a -1 offset from the current
 733  
         // value of indexOfComponentInParent, otherwise, call add()
 734  
 
 735  0
         List<String> childrenAddedIds = (List<String>)parent.getAttributes().get(FORMER_CHILD_IDS_SET_ATTR);
 736  
 
 737  0
         int parentIndex = children.indexOf(component);
 738  
 
 739  0
         if (childrenAddedIds != null)
 740  
         {
 741  0
             if (parentIndex > 0 && childrenAddedIds.size() == parentIndex)
 742  
             {
 743  0
                 UIComponent formerVerbatim = children.get(parentIndex - 1);
 744  
 
 745  0
                 if (formerVerbatim instanceof UIOutput && formerVerbatim.isTransient())
 746  
                 {
 747  0
                     children.set(parentIndex - 1, verbatimComp);
 748  
                 }
 749  
             }
 750  
         }
 751  
 
 752  0
         children.add(parentIndex, verbatimComp);
 753  
 
 754  0
         parentTag.addChild(verbatimComp);
 755  0
     }
 756  
 
 757  
     /**
 758  
      * <p>
 759  
      * Add <i>verbatim</i> as a sibling of <i>_componentInstance</i> in <i>_componentInstance</i> in the parent's child
 760  
      * list. <i>verbatim</i> is added to the list at the position immediatly following <i>_componentInstance</i>.
 761  
      * </p>
 762  
      */
 763  
 
 764  
     protected void addVerbatimAfterComponent(UIComponentClassicTagBase parentTag, UIComponent verbatim,
 765  
                                              UIComponent component)
 766  
     {
 767  0
         int indexOfComponentInParent = 0;
 768  0
         UIComponent parent = component.getParent();
 769  
 
 770  
         // invert the order of this if and the assignment below. Since this line is
 771  
         // here, it appears an early return is acceptable/desired if parent is null,
 772  
         // and, if it is null, we should probably check for that before we try to
 773  
         // access it. 2006-03-15 jdl
 774  0
         if (null == parent)
 775  
         {
 776  0
             return;
 777  
         }
 778  0
         List<UIComponent> children = parent.getChildren();
 779  0
         indexOfComponentInParent = children.indexOf(component);
 780  0
         if (children.size() - 1 == indexOfComponentInParent)
 781  
         {
 782  0
             children.add(verbatim);
 783  
         }
 784  
         else
 785  
         {
 786  0
             children.add(indexOfComponentInParent + 1, verbatim);
 787  
         }
 788  0
         parentTag.addChild(verbatim);
 789  0
     }
 790  
 
 791  
     /**
 792  
      * @deprecated the ResponseWriter is now set by {@link javax.faces.application.ViewHandler#renderView}
 793  
      */
 794  
     protected void setupResponseWriter()
 795  
     {
 796  0
     }
 797  
 
 798  
     /**
 799  
      * Invoke encodeBegin on the associated UIComponent. Subclasses can override this method to perform custom
 800  
      * processing before or after the UIComponent method invocation.
 801  
      */
 802  
     protected void encodeBegin() throws IOException
 803  
     {
 804  0
         if (log.isLoggable(Level.FINE))
 805  
         {
 806  0
             log.fine("Entered encodeBegin for client-Id: " + _componentInstance.getClientId(getFacesContext()));
 807  
         }
 808  0
         _componentInstance.encodeBegin(getFacesContext());
 809  0
         if (log.isLoggable(Level.FINE))
 810  
         {
 811  0
             log.fine("Exited encodeBegin");
 812  
         }
 813  0
     }
 814  
 
 815  
     /**
 816  
      * Invoke encodeChildren on the associated UIComponent. Subclasses can override this method to perform custom
 817  
      * processing before or after the UIComponent method invocation. This is only invoked for components whose
 818  
      * getRendersChildren method returns true.
 819  
      */
 820  
     protected void encodeChildren() throws IOException
 821  
     {
 822  0
         if (log.isLoggable(Level.FINE))
 823  
         {
 824  0
             log.fine("Entered encodeChildren for client-Id: " + _componentInstance.getClientId(getFacesContext()));
 825  
         }
 826  0
         _componentInstance.encodeChildren(getFacesContext());
 827  0
         if (log.isLoggable(Level.FINE))
 828  
         {
 829  0
             log.fine("Exited encodeChildren for client-Id: " + _componentInstance.getClientId(getFacesContext()));
 830  
         }
 831  0
     }
 832  
 
 833  
     /**
 834  
      * Invoke encodeEnd on the associated UIComponent. Subclasses can override this method to perform custom processing
 835  
      * before or after the UIComponent method invocation.
 836  
      */
 837  
     protected void encodeEnd() throws IOException
 838  
     {
 839  0
         if (log.isLoggable(Level.FINE))
 840  
         {
 841  0
             log.fine("Entered encodeEnd for client-Id: " + _componentInstance.getClientId(getFacesContext()));
 842  
         }
 843  0
         _componentInstance.encodeEnd(getFacesContext());
 844  0
         if (log.isLoggable(Level.FINE))
 845  
         {
 846  0
             log.fine("Exited encodeEnd for client-Id: " + _componentInstance.getClientId(getFacesContext()));
 847  
         }
 848  
 
 849  0
     }
 850  
 
 851  
     private boolean isRootTag(UIComponentClassicTagBase parentTag)
 852  
     {
 853  0
         return (parentTag == this);
 854  
     }
 855  
 
 856  
     private boolean isInRenderedChildrenComponent(UIComponentClassicTagBase tag)
 857  
     {
 858  0
         return (_parentClassicTag != null && tag.getComponentInstance().getRendersChildren());
 859  
     }
 860  
 
 861  
     private boolean isFacet()
 862  
     {
 863  0
         return _parent != null && _parent instanceof FacetTag;
 864  
     }
 865  
 
 866  
     /** Map of <ID,Tag> in the view */
 867  
     @SuppressWarnings("unchecked")
 868  
     private Map<String, Object> getViewComponentIds()
 869  
     {
 870  0
         Map<Object, Object> attributes = _facesContext.getAttributes();
 871  
         Map<String, Object> viewComponentIds;
 872  
 
 873  0
         if (_parent == null)
 874  
         {
 875  
             // top level _componentInstance
 876  0
             viewComponentIds = new HashMap<String, Object>();
 877  0
             attributes.put(VIEW_IDS, viewComponentIds);
 878  
         }
 879  
         else
 880  
         {
 881  0
             viewComponentIds = (Map<String, Object>) attributes.get(VIEW_IDS);
 882  
             
 883  
             // Check if null, this can happen if someone programatically tries to do an include of a 
 884  
             // JSP fragment. This code will prevent NullPointerException from happening in such cases.
 885  0
             if (viewComponentIds == null)
 886  
             {
 887  0
                 viewComponentIds = new HashMap<String, Object>();
 888  0
                 attributes.put(VIEW_IDS, viewComponentIds);
 889  
             }
 890  
         }
 891  
 
 892  0
         return viewComponentIds;
 893  
     }
 894  
 
 895  
     @SuppressWarnings("unchecked")
 896  
     private static final Stack<UIComponentClassicTagBase> getStack(PageContext pageContext)
 897  
     {
 898  0
         Stack<UIComponentClassicTagBase> stack =
 899  
                 (Stack<UIComponentClassicTagBase>)pageContext.getAttribute(COMPONENT_STACK_ATTR,
 900  
                     PageContext.REQUEST_SCOPE);
 901  
 
 902  0
         if (stack == null)
 903  
         {
 904  0
             stack = new Stack<UIComponentClassicTagBase>();
 905  0
             pageContext.setAttribute(COMPONENT_STACK_ATTR, stack, PageContext.REQUEST_SCOPE);
 906  
         }
 907  
 
 908  0
         return stack;
 909  
     }
 910  
 
 911  
     /**
 912  
      * The pageContext's request scope map is used to hold a stack of JSP tag objects seen so far, so that a new tag can
 913  
      * find the parent tag that encloses it. Access to the parent tag is used to find the parent UIComponent for the
 914  
      * component associated with this tag plus some other uses.
 915  
      */
 916  
     private void popTag()
 917  
     {
 918  0
         Stack<UIComponentClassicTagBase> stack = getStack(pageContext);
 919  
 
 920  0
         int size = stack.size();
 921  0
         stack.remove(size - 1);
 922  0
         if (size <= 1)
 923  
         {
 924  0
             pageContext.removeAttribute(COMPONENT_STACK_ATTR, PageContext.REQUEST_SCOPE);
 925  
         }
 926  
 
 927  0
     }
 928  
 
 929  
     private void pushTag()
 930  
     {
 931  0
         getStack(pageContext).add(this);
 932  0
     }
 933  
 
 934  
     //private boolean isIncludedOrForwarded() {
 935  
     //    return getFacesContext().getExternalContext().getRequestMap().
 936  
     //            containsKey("javax.servlet.include.request_uri");
 937  
     //}
 938  
 
 939  
     /** Generate diagnostic output. */
 940  
     private String getPathToComponent(UIComponent component)
 941  
     {
 942  0
         StringBuffer buf = new StringBuffer();
 943  
 
 944  0
         if (component == null)
 945  
         {
 946  0
             buf.append("{Component-Path : ");
 947  0
             buf.append("[null]}");
 948  0
             return buf.toString();
 949  
         }
 950  
 
 951  0
         getPathToComponent(component, buf);
 952  
 
 953  0
         buf.insert(0, "{Component-Path : ");
 954  0
         buf.append("}");
 955  
 
 956  0
         return buf.toString();
 957  
     }
 958  
 
 959  
     /** Generate diagnostic output. */
 960  
     private static void getPathToComponent(UIComponent component, StringBuffer buf)
 961  
     {
 962  0
         if (component == null)
 963  
         {
 964  0
             return;
 965  
         }
 966  
 
 967  0
         StringBuffer intBuf = new StringBuffer();
 968  
 
 969  0
         intBuf.append("[Class: ");
 970  0
         intBuf.append(component.getClass().getName());
 971  0
         if (component instanceof UIViewRoot)
 972  
         {
 973  0
             intBuf.append(",ViewId: ");
 974  0
             intBuf.append(((UIViewRoot)component).getViewId());
 975  
         }
 976  
         else
 977  
         {
 978  0
             intBuf.append(",Id: ");
 979  0
             intBuf.append(component.getId());
 980  
         }
 981  0
         intBuf.append("]");
 982  
 
 983  0
         buf.insert(0, intBuf);
 984  
 
 985  0
         getPathToComponent(component.getParent(), buf);
 986  0
     }
 987  
 
 988  
     /**
 989  
      * Remove any child components of the associated components which do not have corresponding tags as children of this
 990  
      * tag. This only happens when a view is being re-rendered and there are components in the view tree which don't
 991  
      * have corresponding JSP tags. Wrapping JSF tags in JSTL "c:if" statements is one way this can happen. <br />
 992  
      * Attention: programmatically added components are are not affected by this: they will not be on the old list of
 993  
      * created components nor on the new list of created components, so nothing will happen to them.
 994  
      */
 995  
     @SuppressWarnings("unchecked")
 996  
     private void removeFormerChildren(UIComponent component)
 997  
     {
 998  0
         List<String> formerChildIds = (List<String>)component.getAttributes().get(FORMER_CHILD_IDS_SET_ATTR);
 999  0
         if (formerChildIds != null)
 1000  
         {
 1001  0
             for (String childId : formerChildIds)
 1002  
             {
 1003  0
                 if (_childrenAdded == null || !_childrenAdded.contains(childId))
 1004  
                 {
 1005  0
                     UIComponent childToRemove = component.findComponent(childId);
 1006  0
                     if (childToRemove != null)
 1007  
                     {
 1008  0
                         component.getChildren().remove(childToRemove);
 1009  
                     }
 1010  
                 }
 1011  0
             }
 1012  0
             if (_childrenAdded == null)
 1013  
             {
 1014  0
                 component.getAttributes().remove(FORMER_CHILD_IDS_SET_ATTR);
 1015  
             }
 1016  
             else
 1017  
             {
 1018  0
                 component.getAttributes().put(FORMER_CHILD_IDS_SET_ATTR, _childrenAdded);
 1019  
             }
 1020  
         }
 1021  
         else
 1022  
         {
 1023  0
             if (_childrenAdded != null)
 1024  
             {
 1025  0
                 component.getAttributes().put(FORMER_CHILD_IDS_SET_ATTR, _childrenAdded);
 1026  
             }
 1027  
         }
 1028  0
     }
 1029  
 
 1030  
     /** See removeFormerChildren. */
 1031  
     @SuppressWarnings("unchecked")
 1032  
     private void removeFormerFacets(UIComponent component)
 1033  
     {
 1034  0
         List<String> formerFacetNames = (List<String>)component.getAttributes().get(FORMER_FACET_NAMES_SET_ATTR);
 1035  0
         if (formerFacetNames != null)
 1036  
         {
 1037  0
             for (String facetName : formerFacetNames)
 1038  
             {
 1039  0
                 if (_facetsAdded == null || !_facetsAdded.contains(facetName))
 1040  
                 {
 1041  0
                     component.getFacets().remove(facetName);
 1042  
                 }
 1043  0
             }
 1044  0
             if (_facetsAdded == null)
 1045  
             {
 1046  0
                 component.getAttributes().remove(FORMER_FACET_NAMES_SET_ATTR);
 1047  
             }
 1048  
             else
 1049  
             {
 1050  0
                 component.getAttributes().put(FORMER_FACET_NAMES_SET_ATTR, _facetsAdded);
 1051  
             }
 1052  
         }
 1053  
         else
 1054  
         {
 1055  0
             if (_facetsAdded != null)
 1056  
             {
 1057  0
                 component.getAttributes().put(FORMER_FACET_NAMES_SET_ATTR, _facetsAdded);
 1058  
             }
 1059  
         }
 1060  0
     }
 1061  
 
 1062  
     /**
 1063  
      * Return the corresponding UIComponent for this tag, creating it if necessary.
 1064  
      * <p>
 1065  
      * If this is not the first time this method has been called, then return the cached _componentInstance instance
 1066  
      * found last time.
 1067  
      * <p>
 1068  
      * If this is not the first time this view has been seen, then locate the existing _componentInstance using the id
 1069  
      * attribute assigned to this tag and return it. Note that this is simple for components with user-assigned ids. For
 1070  
      * components with generated ids, the "reattachment" relies on the fact that UIViewRoot will generate the same id
 1071  
      * values for tags in this page as it did when first generating the view. For this reason all JSF tags within a JSTL
 1072  
      * "c:if" are required to have explicitly-assigned ids.
 1073  
      * <p>
 1074  
      * Otherwise create the _componentInstance, populate its properties from the xml attributes on this JSP tag and
 1075  
      * attach it to its parent.
 1076  
      * <p>
 1077  
      * When a _componentInstance is found or created the parent JSP tag is also told that the _componentInstance has
 1078  
      * been "seen". When the parent tag ends it will delete any components which were in the view previously but have
 1079  
      * not been seen this time; see doEndTag for more details.
 1080  
      */
 1081  
     protected UIComponent findComponent(FacesContext context) throws JspException
 1082  
     {
 1083  
         // 1. If we have previously located this component, return it.
 1084  0
         if (_componentInstance != null)
 1085  
         {
 1086  0
             return _componentInstance;
 1087  
         }
 1088  
 
 1089  
         // 2. Locate the parent component by looking for a parent UIComponentTag instance,
 1090  
         // and ask it for its component. If there is no parent UIComponentTag instance,
 1091  
         // this tag represents the root component, so get it from the current Tree and return it.
 1092  0
         UIComponentClassicTagBase parentTag = getParentUIComponentClassicTagBase(pageContext);
 1093  
 
 1094  0
         if (parentTag == null)
 1095  
         {
 1096  
             // This is the root
 1097  0
             _componentInstance = context.getViewRoot();
 1098  
 
 1099  
             // check if the view root is already bound to the tag
 1100  0
             Object alreadyBoundViewRootFlag = _componentInstance.getAttributes().get(BOUND_VIEW_ROOT);
 1101  
 
 1102  0
             if (alreadyBoundViewRootFlag == null)
 1103  
             {
 1104  
                 try
 1105  
                 {
 1106  0
                     setProperties(_componentInstance);
 1107  
                 }
 1108  0
                 catch (Throwable e)
 1109  
                 {
 1110  0
                     throw new JspException(e);
 1111  0
                 }
 1112  
 
 1113  0
                 if (_id != null)
 1114  
                 {
 1115  0
                     _componentInstance.setId(_id);
 1116  
                 }
 1117  
                 else
 1118  
                 {
 1119  0
                     _componentInstance.setId(getFacesJspId());
 1120  
                 }
 1121  0
                 _componentInstance.getAttributes().put(BOUND_VIEW_ROOT, true);
 1122  0
                 _created = true;
 1123  
 
 1124  
             }
 1125  0
             else if (hasBinding())
 1126  
             {
 1127  0
                 setProperties(_componentInstance);
 1128  
             }
 1129  
 
 1130  0
             return _componentInstance;
 1131  
         }
 1132  
 
 1133  0
         UIComponent parent = parentTag.getComponentInstance();
 1134  
 
 1135  0
         if (parent == null)
 1136  
         {
 1137  0
             throw new IllegalStateException("parent is null?");
 1138  
         }
 1139  
 
 1140  0
         String facetName = getFacetName();
 1141  0
         if (facetName != null)
 1142  
         {
 1143  
             // Facet
 1144  0
             String id = createUniqueId(context, parent);
 1145  0
             _componentInstance = parent.getFacet(facetName);
 1146  0
             if (_componentInstance == null)
 1147  
             {
 1148  0
                 _componentInstance = createComponent(context, id);
 1149  0
                 _created = true;
 1150  0
                 parent.getFacets().put(facetName, _componentInstance);
 1151  
             }
 1152  
             else
 1153  
             {
 1154  0
                 if (checkFacetNameOnParentExists(parentTag, facetName))
 1155  
                 {
 1156  0
                     throw new IllegalStateException("facet '" + facetName
 1157  
                             + "' already has a child associated. current associated _componentInstance id: "
 1158  
                             + _componentInstance.getClientId(context) + " class: "
 1159  
                             + _componentInstance.getClass().getName());
 1160  
                 }
 1161  
             }
 1162  
 
 1163  0
             addFacetNameToParentTag(parentTag, facetName);
 1164  0
             return _componentInstance;
 1165  
         }
 1166  
 
 1167  
         // Child
 1168  
         //
 1169  
         // Note that setProperties is called only when we create the
 1170  
         // _componentInstance; on later passes, the attributes defined on the
 1171  
         // JSP tag are set on this Tag object, but then completely
 1172  
         // ignored.
 1173  
 
 1174  0
         String id = createUniqueId(context, parent);
 1175  
 
 1176  
         // Warn users that this tag is about to find/steal the UIComponent
 1177  
         // that has already been created for a sibling tag with the same id value .
 1178  
         // _childrenAdded is a Set, and we will stomp over a past id when calling
 1179  
         // addChildIdToParentTag.
 1180  
         //
 1181  
         // It would also be reasonable to throw an exception here rather than
 1182  
         // just issue a warning as this is a pretty serious problem. However the
 1183  
         // Sun RI just issues a warning...
 1184  0
         if (parentTag._childrenAdded != null && parentTag._childrenAdded.contains(id))
 1185  
         {
 1186  0
             if (log.isLoggable(Level.WARNING))
 1187  
             {
 1188  0
                 log.warning("There is more than one JSF tag with an id : " + id);
 1189  
             }
 1190  
         }
 1191  
 
 1192  0
         _componentInstance = findComponent(parent, id);
 1193  0
         if (_componentInstance == null)
 1194  
         {
 1195  0
             _componentInstance = createComponent(context, id);
 1196  0
             if (id.equals(_componentInstance.getId()) )
 1197  
             {
 1198  0
             _created = true;
 1199  0
             int index = parentTag.getIndexOfNextChildTag();
 1200  0
             if (index > parent.getChildCount())
 1201  
             {
 1202  0
                 index = parent.getChildCount();
 1203  
             }
 1204  
 
 1205  0
             List<UIComponent> children = parent.getChildren();
 1206  0
             children.add(index, _componentInstance);
 1207  0
         }
 1208  
             // On weblogic portal using faces-adapter, the id set and the retrieved 
 1209  
             // one for <netuix:namingContainer> is different. The reason is 
 1210  
             // this custom solution for integrate jsf changes the id of the parent
 1211  
             // component to allow the same native portlet to be allocated multiple
 1212  
             // times in the same page
 1213  0
             else if (null == findComponent(parent,_componentInstance.getId()))
 1214  
             {
 1215  0
                 _created = true;
 1216  0
                 int index = parentTag.getIndexOfNextChildTag();
 1217  0
                 if (index > parent.getChildCount())
 1218  
                 {
 1219  0
                     index = parent.getChildCount();
 1220  
                 }
 1221  
 
 1222  0
                 List<UIComponent> children = parent.getChildren();
 1223  0
                 children.add(index, _componentInstance);
 1224  
             }
 1225  
         }
 1226  
 
 1227  0
         return _componentInstance;
 1228  
 
 1229  
     }
 1230  
 
 1231  
     private UIComponent findComponent(UIComponent parent, String id)
 1232  
     {
 1233  0
         for (UIComponent child : parent.getChildren())
 1234  
         {
 1235  0
             if (child.getId() != null && child.getId().equals(id))
 1236  
             {
 1237  0
                 return child;
 1238  
             }
 1239  0
         }
 1240  
 
 1241  0
         return null;
 1242  
     }
 1243  
 
 1244  
     private String createUniqueId(FacesContext context, UIComponent parent) throws JspException
 1245  
     {
 1246  0
         String id = getId();
 1247  0
         if (id == null)
 1248  
         {
 1249  0
             id = getFacesJspId();
 1250  
         }
 1251  0
         else if (isIdDuplicated(id))
 1252  
         {
 1253  0
             if (isInAnIterator)
 1254  
             {
 1255  0
                 setId(createNextId(id));
 1256  0
                 id = getId();
 1257  
             }
 1258  
             else
 1259  
             {
 1260  0
                 if (parent != null)
 1261  
                 {
 1262  
 
 1263  
                     UIComponent namingContainer;
 1264  
 
 1265  0
                     if (parent instanceof NamingContainer)
 1266  
                     {
 1267  0
                         namingContainer = parent;
 1268  
                     }
 1269  
                     else
 1270  
                     {
 1271  0
                         namingContainer = parent.getParent();
 1272  
                     }
 1273  
 
 1274  0
                     if (namingContainer != null)
 1275  
                     {
 1276  0
                         UIComponent component = namingContainer.findComponent(id);
 1277  
 
 1278  0
                         if (component == null || isPostBack(context))
 1279  
                         {
 1280  0
                             return id;
 1281  
                         }
 1282  
                     }
 1283  
                 }
 1284  
 
 1285  0
                 throw new JspException("Duplicated Id found in the view: " + id);
 1286  
             }
 1287  
         }
 1288  
 
 1289  0
         return id;
 1290  
     }
 1291  
 
 1292  
     private String createNextId(String componentId)
 1293  
     {
 1294  0
         Integer currentCounter = (Integer) getFacesContext().getAttributes().get(componentId);
 1295  
 
 1296  0
         int iCurrentCounter = 1;
 1297  
 
 1298  0
         if (currentCounter != null)
 1299  
         {
 1300  0
             iCurrentCounter = currentCounter;
 1301  0
             iCurrentCounter++;
 1302  
         }
 1303  
 
 1304  0
         getFacesContext().getAttributes().put(componentId, iCurrentCounter);
 1305  
 
 1306  
         //if (isIncludedOrForwarded())
 1307  
         //{
 1308  
         //    componentId = componentId + "pc" + iCurrentCounter;
 1309  
         //}
 1310  
         //else
 1311  
         //{
 1312  0
         componentId = componentId + UNIQUE_ID_PREFIX + iCurrentCounter;            
 1313  
         //}
 1314  
 
 1315  0
         return componentId;
 1316  
     }
 1317  
 
 1318  
     private void checkIfItIsInAnIterator(String jspId)
 1319  
     {
 1320  0
         Set<String> previousJspIdsSet = getPreviousJspIdsSet();
 1321  
 
 1322  0
         if (previousJspIdsSet.contains(jspId))
 1323  
         {
 1324  0
             isInAnIterator = true;
 1325  
         }
 1326  
         else
 1327  
         {
 1328  0
             previousJspIdsSet.add(jspId);
 1329  0
             isInAnIterator = false;
 1330  
         }
 1331  0
     }
 1332  
 
 1333  
     @SuppressWarnings("unchecked")
 1334  
     private Set<String> getPreviousJspIdsSet()
 1335  
     {
 1336  0
         Set<String> previousJspIdsSet =
 1337  
                 (Set<String>)getFacesContext().getAttributes().get(PREVIOUS_JSP_IDS_SET);
 1338  
 
 1339  0
         if (previousJspIdsSet == null)
 1340  
         {
 1341  0
             previousJspIdsSet = new HashSet<String>();
 1342  
             // Add it to the context! The next time is called
 1343  
             // this method it takes the ref from the RequestContext
 1344  0
             getFacesContext().getAttributes().put(PREVIOUS_JSP_IDS_SET, previousJspIdsSet);
 1345  
         }
 1346  
 
 1347  0
         return previousJspIdsSet;
 1348  
     }
 1349  
 
 1350  
     private boolean isIdDuplicated(String componentId)
 1351  
     {
 1352  0
         boolean result = false;
 1353  0
         if (_parentClassicTag != null)
 1354  
         {
 1355  0
             if (_parentClassicTag.isInAnIterator)
 1356  
             {
 1357  0
                 return true;
 1358  
             }
 1359  0
             List<String> childComponents = _parentClassicTag.getCreatedComponents();
 1360  
 
 1361  0
             if (childComponents != null)
 1362  
             {
 1363  0
                 result = childComponents.contains(componentId);
 1364  0
                 if (result && (!isInAnIterator))
 1365  
                 {
 1366  0
                     return true;
 1367  
                 }
 1368  
             }
 1369  
         }
 1370  
 
 1371  0
         return result;
 1372  
     }
 1373  
 
 1374  
     private boolean isPostBack(FacesContext facesContext)
 1375  
     {
 1376  0
         return facesContext.getExternalContext().getRequestParameterMap().containsKey(
 1377  
             ResponseStateManager.VIEW_STATE_PARAM);
 1378  
     }
 1379  
 
 1380  
     /**
 1381  
      * check if the facet is already added to the parent
 1382  
      */
 1383  
     private boolean checkFacetNameOnParentExists(UIComponentClassicTagBase parentTag, String facetName)
 1384  
     {
 1385  0
         return parentTag._facetsAdded != null && parentTag._facetsAdded.contains(facetName);
 1386  
     }
 1387  
 
 1388  
     /**
 1389  
      * Notify the enclosing JSP tag of the id of this facet's id. The parent tag will later delete any existing view
 1390  
      * facets that were not seen during this rendering phase; see doEndTag for details.
 1391  
      */
 1392  
     private void addFacetNameToParentTag(UIComponentClassicTagBase parentTag, String facetName)
 1393  
     {
 1394  0
         if (parentTag._facetsAdded == null)
 1395  
         {
 1396  0
             parentTag._facetsAdded = new ArrayList<String>();
 1397  
         }
 1398  0
         parentTag._facetsAdded.add(facetName);
 1399  0
     }
 1400  
 
 1401  
     protected abstract boolean hasBinding();
 1402  
 
 1403  
     public JspWriter getPreviousOut()
 1404  
     {
 1405  0
         return bodyContent.getEnclosingWriter();
 1406  
     }
 1407  
 }