Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    */
   
   /*
    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    *
    * Copyright 1997-2010 Sun Microsystems, Inc. All rights reserved.
    *
    * The contents of this file are subject to the terms of either the GNU
   * General Public License Version 2 only ("GPL") or the Common Development
   * and Distribution License("CDDL") (collectively, the "License").  You
   * may not use this file except in compliance with the License. You can obtain
   * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
   * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
   * language governing permissions and limitations under the License.
   *
   * When distributing the software, include this License Header Notice in each
   * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
   * Sun designates this particular file as subject to the "Classpath" exception
   * as provided by Sun in the GPL Version 2 section of the License file that
   * accompanied this code.  If applicable, add the following below the License
   * Header, with the fields enclosed by brackets [] replaced by your own
   * identifying information: "Portions Copyrighted [year]
   * [name of copyright owner]"
   *
   * Contributor(s):
   *
   * If you wish your version of this file to be governed by only the CDDL or
   * only the GPL Version 2, indicate your decision by adding "[Contributor]
   * elects to include this software in this distribution under the [CDDL or GPL
   * Version 2] license."  If you don't indicate a single choice of license, a
   * recipient has the option to distribute your version of this file under
   * either the CDDL, the GPL Version 2 or to extend the choice of license to
   * its licensees as provided above.  However, if you add GPL Version 2 code
   * and therefore, elected the GPL Version 2 license, then the option applies
   * only if the new code is made subject to such option by the copyright
   * holder.
   */
  
  package javax.faces.webapp;
  import  javax.servlet.jsp.jstl.core.LoopTag;
  
  import java.io.Writer;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;

UIComponentTagBase is the base class for all JSP tags that use the "classic" JSP tag interface that correspond to a javax.faces.component.UIComponent instance in the view. In Faces 1.2, all component tags are BodyTag instances to allow for the execution of the page to build the component tree, but not render it. Rendering happens only after the component tree is completely built.

UIComponentTag extends UIComponentClassicTagBase to add support for properties that conform to the Faces 1.1 EL.

UIComponentELTag extends UIComponentClassicTagBase class to add support for properties that conform to the EL API.

The default implementation allows the proper interweaving of template text, non-Faces JSP tag output, and Faces component tag output in the same page, as expected by the page author.

The CASE markers in the following example will be cited in the method descriptions of this class.

  • CASE 1 describes template text and/or non-component custom tag output occurring as the child of a component tag, but before the first component tag child of that component tag.

  • CASE 2 describes template text and/or non-component custom tag output occurring between two sibling component tags.

  • CASE 3 describes template text and/or non-component custom tag output occurring as the child content of an <f:verbatim> tag at any point in the page.

  • CASE 4 describes template text and/or non-component custom tag output occurring between the last child component tag and its enclosing parent component tag's end tag.


<h:panelGrid style="color:red" border="4" columns="2">
CASE 1
<h:outputText value="component 1"/>
CASE 2
<h:outputText value="component 2"/>
<f:verbatim>CASE 3</f:verbatim>
<c:out value="${pageScope.CASE4}" />
</h:panelGrid>

 

The preceding arrangement of faces component tags, must yield markup that will render identically to the following (assuming that ${pageScope.CASE4} evaluates to "CASE 4" without the quotes).


<table border="4" style="color:red">

<tbody>

<tr><td>CASE 1</td></tr> <tr><td>component 1</td></tr>

<tr><td>CASE 2</td> <tr><td>component 2</td></tr>

<tr><td>CASE 3</td> <td>CASE 4</td></tr>

</tbody>

</table>

 
 
 
 public abstract class UIComponentClassicTagBase extends UIComponentTagBase implements JspIdConsumerBodyTag {
 
     // ------------------------------------------------------ Manifest Constants
     

The request scope attribute under which a component tag stack for the current request will be maintained.

 
     private static final String COMPONENT_TAG_STACK_ATTR =
         "javax.faces.webapp.COMPONENT_TAG_STACK";

    

A request scoped map that takes the place of calls to the request map directly.

IMPORTANT. This map is accessed via literal string in ViewTag.doEndTag().

 
     private static final String CONTEXT_MAP_ATTR =
         "com.sun.faces.CONTEXT_MAP";

    

The UIComponent attribute under which we will store a List of the component identifiers of child components created on the previous generation of this page (if any).

 
     private static final String JSP_CREATED_COMPONENT_IDS =
         "javax.faces.webapp.COMPONENT_IDS";


    

The UIComponent attribute under which we will store a List of the facet names of facets created on the previous generation of this page (if any).

 
     private static final String JSP_CREATED_FACET_NAMES =
         "javax.faces.webapp.FACET_NAMES";


    

The attribute name under which we will store the FacesContext for this request.

 
     private static final String CURRENT_FACES_CONTEXT =
         "javax.faces.webapp.CURRENT_FACES_CONTEXT";

    

The attribute name under which we will store the UIViewRoot for this request.

 
     private static final String CURRENT_VIEW_ROOT =
         "javax.faces.webapp.CURRENT_VIEW_ROOT";

    
Used as the prefix for ids. This is necessary to avoid uniqueness conflicts with the transient verbatim components.
 
     protected static final String UNIQUE_ID_PREFIX =
 	. + '_';

    
Used to store the previousJspId Map in requestScope
 
     private static final String PREVIOUS_JSP_ID_SET =
 	"javax.faces.webapp.PREVIOUS_JSP_ID_SET";

    
This is a Page scoped marker to help us keep track of the different execution context we could be operating within, e.g. an include, or a tag file. The value of the attribute is an Integer that is unqiue to this page context.
 
     private static final String JAVAX_FACES_PAGECONTEXT_MARKER =
          "javax.faces.webapp.PAGECONTEXT_MARKER";

    
This is a request scoped attribute which contains an AtomicInteger which we use to increment the PageContext count.
 
     private static final String JAVAX_FACES_PAGECONTEXT_COUNTER =
          "javax.faces.webapp.PAGECONTEXT_COUNTER";
 
     
     // ------------------------------------------------------ Instance Variables
     

The bodyContent for this tag handler.

 
     protected BodyContent bodyContent = null;

    

The UIComponent that is being encoded by this tag, if any.

 
     private UIComponent component = null;


    

The FacesContext for the request being processed, if any.

 
     private FacesContext context = null;


    

Was a new component instance dynamically created when our findComponent() method was called.

 
     private boolean created = false;


    

The Lst of UIComponent ids created or located by nested UIComponentTags while processing the current request.

 
     private List<StringcreatedComponents = null;


    

The List of facet names created or located by nested UIComponentTags while processing the current request.

 
     private List<StringcreatedFacets = null;


    

The JSP PageContext for the page we are embedded in.

 
     protected PageContext pageContext = null;


    

The JSP Tag that is the parent of this tag.

 
     private Tag parent = null;

    
setJspId
 
 
     private String jspId = null;

    
Only consulted in setJspId to detect the iterator case. Set in release. Never cleared.
 
 
     //private String oldJspId = null;
 
    
This is simply the jspId prefixed by UNIQUE_ID_PREFIX.
 
 
     private String facesJspId = null;

    

The component identifier for the associated component.

 
     private String id = null;

    
Caches the nearest enclosing UIComponentClassicTagBase of this tag. This is used for duplicate id detection.
 
     private UIComponentClassicTagBase parentTag = null;

    
Set to true if this component is nested inside of an iterating tag
 
     private boolean isNestedInIterator = false;

  
The next child index to get in getChild()
 
   private int _nextChildIndex = 0;

    
private context Map For Lookups
 
     Map<StringObjectcontextMap = null;
 
 
     public UIComponentClassicTagBase() {}
     
     UIComponentClassicTagBase(PageContext pageContextFacesContext facesContext) {
         this. = pageContext;
         this. = facesContext;
     }
 
 
     // --------------------------------------------- Support Methods for Tag
 
     //
     // Simple methods to be overridden by subclasses if necessary
     //
 
    

Return the flag value that should be returned from the doStart() method when it is called. Subclasses may override this method to return the appropriate value.

Throws:
JspException to cause doStart() to throw an exception
 
     protected int getDoStartValue() throws JspException {
 
 	int result = ;
 
 	return result;
     }

    

Return the flag value that should be returned from the doEnd() method when it is called. Subclasses may override this method to return the appropriate value.

Throws:
JspException to cause doEnd() to throw an exception
 
     protected int getDoEndValue() throws JspException {
 
         return ();
 
     }

    

Delegate to the encodeBegin() method of our corresponding UIComponent. This method is called from doStartTag(). Normally, delegation occurs unconditionally; however, this method is abstracted out so that advanced tags can conditionally perform this call.

Deprecated:
No encoding is done during JSP page execution. Encoding is deferred until the page has completed executing to allow the entire tree to be built before any encoding occurs.
Throws:
IOException if an input/output error occurs
 
     protected void encodeBegin() throws IOException {
 
         .encodeBegin();
 
     }


    

Delegate to the encodeChildren() method of our corresponding UIComponent. This method is called from doStartTag(). Normally, delegation occurs unconditionally; however, this method is abstracted out so that advanced tags can conditionally perform this call.

Deprecated:
No encoding is done during JSP page execution. Encoding is deferred until the page has completed executing to allow the entire tree to be built before any encoding occurs.
Throws:
IOException if an input/output error occurs
 
     protected void encodeChildren() throws IOException {
 
         .encodeChildren();
 
     }


    

Delegate to the encodeEnd() method of our corresponding UIComponent. This method is called from doStartTag(). Normally, delegation occurs unconditionally; however, this method is abstracted out so that advanced tags can conditionally perform this call.

Deprecated:
No encoding is done during JSP page execution. Encoding is deferred until the page has completed executing to allow the entire tree to be built before any encoding occurs.
Throws:
IOException if an input/output error occurs
 
     protected void encodeEnd() throws IOException {
 
         .encodeEnd();
 
     }
 
     // --------------------------------------------------------- Tag Properties
 

    

Set the PageContext of the page containing this tag instance.

Parameters:
pageContext The enclosing PageContext
 
     public void setPageContext(PageContext pageContext) {
 
         this. = pageContext;
 
     }


    

Return the Tag that is the parent of this instance.

 
     public Tag getParent() {
 
         return (this.);
 
     }


    

Set the Tag that is the parent of this instance.

Parameters:
parent The new parent Tag
 
     public void setParent(Tag parent) {
 
         this. = parent;
 
     }
 
 
 
 
     //
     // Complex methods to support Tag
     //
 
    

Set up the javax.faces.context.ResponseWriter for the current response, if this has not been done already.

@deprecated. javax.faces.application.ViewHandler.renderView is now responsible for setting up the response writer. This method is now a no-op.

 
     protected void setupResponseWriter() {
     }


    

Create a new child component using createComponent, initialize its properties, and add it to its parent as a child.

Parameters:
context FacesContext for the current request
parent Parent UIComponent for the new child
componentId Component identifier for the new child, or null for no explicit identifier
 
     private UIComponent createChild(
      FacesContext context,
      UIComponent parent,
      UIComponentClassicTagBase parentTag,
      String componentIdthrows JspException {
 
         UIComponent component = createComponent(contextcomponentId);
               
         int indexOfNextChildTag = parentTag.getIndexOfNextChildTag();
         if (indexOfNextChildTag > parent.getChildCount()) {
             indexOfNextChildTag = parent.getChildCount();
         }
         parent.getChildren().add(indexOfNextChildTagcomponent);
          = true;
         return (component);
 
     }

    

Create a new child component using createComponent, initialize its properties, and add it to its parent as a facet.

Parameters:
context FacesContext for the current request
parent Parent UIComponent of the new facet
name Name of the new facet
newId id of the new facet
 
     private UIComponent createFacet(FacesContext contextUIComponent parent,
                                     String nameString newIdthrows JspException {
 
         UIComponent component = createComponent(contextnewId);
         parent.getFacets().put(namecomponent);
          = true;
         return (component);
 
     }

    

Return a child with the specified component id from the specified component, if any; otherwise, return null.

Parameters:
component UIComponent to be searched
componentId Component id to search for
 
     private static UIComponent getChild(
       UIComponentClassicTagBase tagUIComponent componentString componentId)
     {
       int childCount = component.getChildCount();
       
       // we only need to bother to check if we even have children
       if (childCount > 0)
       {
         List<UIComponentchildren = component.getChildren();
         
         // Most Lists implement RandomAccess, so iterate directly rather than creating
         // and iterator
         if (children instanceof RandomAccess)
         {
           // in the most common case, the first component we are asked for will be the
           // our first child, the second, our second, etc.  Take advantage of this by
           // remembering the index to check for the next child.  This changes this code
           // from O(n^2) for all of the children to O(n)
           int startIndex;
           
           if (tag != null)
             startIndex = tag._nextChildIndex;
           else
             startIndex = 0;
           
           // start searching from location remembered from last time
           for (int i = startIndexi < childCounti++)
           {
             UIComponent child = children.get(i);
             
             if (componentId.equals(child.getId()))
             { 
               // bump up the index to search next and wrap around
               i++;
               
               tag._nextChildIndex = (i < childCount) ? i : 0;
               return child;
             }
           }
           
           // handle case where we started past the first item and didn't find our
           // child.  Now search from the beginning to where we started
           if (startIndex > 0)
           {
             for (int i = 0; i < startIndexi++)
             {
               UIComponent child = children.get(i);
               
               if (componentId.equals(child.getId()))
               {              
                 i++;
                 
                 tag._nextChildIndex = i;
                 return child;
               }
             }            
           }
         }
         else
         {
           // List doesn't support RandomAccess, do it the iterator way
           for (UIComponent child : children)
           {
             if (componentId.equals(child.getId()))
               return child;            
           }
         }
       }
       
       return null;
     }

    

Find and return the UIComponent, from the component tree, that corresponds to this tag handler instance. If there is no such UIComponent, create one and add it as a child or facet of the UIComponent associated with our nearest enclosing UIComponentTag. The process for locating or creating the component is:

  1. If we have previously located this component, return it.
  2. Locate the parent component by looking for a parent UIComponentTag instance, and ask it for its component. If there is no parent UIComponentTag instance, this tag represents the root component, so get it from the current Tree and return it.
  3. If this UIComponentTag instance has the facetName attribute set, ask the parent UIComponent for a facet with this name. If not found, create one, call setProperties() with the new component as a parameter, and register it under this name. Return the found or created facet UIComponent.
  4. Determine the component id to be assigned to the new component, as follows: if this UIComponentTag has an id attribute set, use that value; otherwise, generate an identifier that is guaranteed to be the same for this UIComponent every time this page is processed (i.e. one based on the location of all UIComponentTag instances without an id attribute set).
  5. Ask the parent UIComponent for a child with this identifier. If not found, create one, call setProperties() with the new component as a parameter, and register it as a child with this identifier. Return the found or created child UIComponent.

When creating a component, the process is:

  1. Retrieve the component type by calling UIComponentTag.getComponentType
  2. If the component has a binding attribute, create an expression from it, and call Application.createComponent with that expression, the FacesContext, and the component type. Store the expression using the key "binding".
  3. Otherwise, call Application.createComponent with only the component type.
  4. Call setProperties().
  5. Add the new component as a child or facet of its parent
 
   protected UIComponent findComponent(FacesContext contextthrows JspException
   {
     // Step 1 -- Have we already found the relevant component?
     if ( != null)
     {
       return ();
     }
 
     // Step 2 -- Identify the component that is, or will be, our parent
     UIComponent parentComponent;
     
     if (parentTag != null)
     {
       parentComponent = parentTag.getComponentInstance();
     }
     else
     {      
       // Special case.  The component to be found is the
       // UIViewRoot.
       // see if this is the first time this tag instance is trying
       // to be bound to the UIViewRoot
       parentComponent = context.getViewRoot();
       
       // Has this UIViewRoot instance had a tag bound to it
       // before?
       if (null == parentComponent.getAttributes().get())
       {
         // No it hasn't.
         
         // make sure setProperties() and setId() are called
         // once per UIViewRoot instance.
         try
         {
           setProperties(parentComponent);
         }
         catch (FacesException e)
         {
           if (e.getCause() instanceof JspException)
           {
             throw ((JspException)e.getCause());
           }
           throw e;
         }
 
         if (null != this.)
         {
           parentComponent.setId(this.);
         }
         else
         {
           assert(null != getFacesJspId());
           parentComponent.setId(getFacesJspId());
         }
         
         parentComponent.getAttributes().put();
          = true;
       }
       else if (hasBinding())
       {
         try
         {
           setProperties(parentComponent);
         }
         catch (FacesException e)
         {
           if (e.getCause() instanceof JspException)
           {
             throw ((JspException)e.getCause());
           }
           throw e;
         }
       }
 
       // this is not the first time this tag instance is trying to
       // be bound to this UIViewRoot, take no extra action.
        = parentComponent;
       return ();
     }
 
     // Step 3 -- Calculate the component identifier for this component
     String newId = createId(context);
 
     // Step 4 -- Create or return a facet with the specified name (if any)
     String facetName = getFacetName();
     boolean created = parentTag.getCreated();
     
     if (facetName != null)
     {
       // =-= bts figure out why this didn't work
       // if (!created)
          = parentComponent.getFacets().get(facetName);
       
       if ( == null)
       {
          = createFacet(contextparentComponentfacetNamenewId);
       }
       
       return ();
     }
     else
     {
       // Step 5 -- Create or return a child with the specified id if the parent
       // wasn't newly created and therefore can't already contain the component
       
       // =-= bts figure out why this didn't work
       // if (!created)
        = getChild(parentTagparentComponentnewId);
 
       if ( == null)
       {
          = createChild(contextparentComponentparentTagnewId);
       }
 
       return ();
     }
   }
 
     //
     // Tag tree navigation
     //
 
  

Locate and return the nearest enclosing UIComponentClassicTagBase if any; otherwise, return null.

Parameters:
context PageContext for the current page
 
   {
   }
 
     FacesContext facesContext)
   {
       return _getParentUIComponentClassicTagBase(_getContextMap(facesContext));
   }
 
     List list = null;
 
     if (cMap != null) {
         list = (ListcMap.get();
     }
 
     if (list != null)
     {
       return ((UIComponentClassicTagBaselist.get(list.size() - 1));
     }
     else
     {
       return null;
     }
 
   }
 
     //
     // Methods related to the createdComponents and createdFacets lists.
     //
 
     protected int getIndexOfNextChildTag() {
 
         if ( != null) {
             return (.size());
         } else {
             return (0);
         }
 
     }
 
     protected void addChild(UIComponent child) {
 
         if ( == null) {
              = new ArrayList<String>(6);
         }
         .add(child.getId());
     }
 
     /*
      * Adds argument child to component tree as a child of this component.
      */
     
     void addChildToComponentAndTag(UIComponent child) {
         UIComponent myComponent = this.getComponentInstance();
 
         int indexOfNextChildTag = this.getIndexOfNextChildTag();
         if (indexOfNextChildTag > myComponent.getChildCount()) {
             indexOfNextChildTag = myComponent.getChildCount();
         }
         myComponent.getChildren().add(indexOfNextChildTagchild);
         this.addChild(child);        
     }
 
     protected void addFacet(String name) {
 
         if ( == null) {
             //noinspection CollectionWithoutInitialCapacity
              = new ArrayList<String>(3);
         }
         .add(name);
 
     }

    

Pop the top UIComponentTag instance off of our component tag stack, deleting the stack if this was the last entry.

 
     private void popUIComponentClassicTagBase() {
         assert(null != );
         List list = (List.get();
 
         // if an exception occurred in a nested  tag,
         //there could be a few tags left in the stack.
         UIComponentClassicTagBase uic = null;
         while (list != null && uic != this) {
             int idx = list.size() - 1;
             uic = (UIComponentClassicTagBaselist.get(idx);
             list.remove(idx);
             if (idx < 1) {
                 .remove();
                 list = null;
             }
         }
     }


    

Push the specified UIComponentTag instance onto our component tag stack, creating a stack if necessary.

 
     private void pushUIComponentClassicTagBase() {
 
         assert (null != );
         List<UIComponentClassicTagBaselist = TypedCollections.dynamicallyCastList((List)
               .get(), UIComponentClassicTagBase.class);
         if (list == null) {
             //noinspection CollectionWithoutInitialCapacity
             list = new ArrayList<UIComponentClassicTagBase>();
             .put(list);
         }
         list.add(this);
 
     }

  
Similar to List.indexOf, except that we start searching from a specific index and then wrap aroud. For this to be performant, the List should implement RandomAccess.

Parameters:
<T>
list List to seatch
startIndex index to start searching for value from
searchValue Value to search for (null not supported)
Returns:
The index at which the value was first found, or -1 if not found
 
   private static int _indexOfStartingFrom(List<?> listint startIndexObject searchValue)
   {
     int itemCount = list.size();
     
     boolean found = false;
     
     // start searching from location remembered from last time
     for (int currIndex = startIndexcurrIndex < itemCountcurrIndex++)
     {
       Object currId = list.get(currIndex);
       
       if ((searchValue == currId) || ((searchValue != null) && searchValue.equals(currId)))
       {
         return currIndex;
       }
     }
     
     // handle case where we started past the first item and didn't find the
     // searchValue.  Now search from the beginning to where we started
     if (startIndex > 0)
     {
       for (int currIndex = 0; currIndex < startIndexcurrIndex++)
       {        
         Object currId = list.get(currIndex);
         
         if ((searchValue == currId) || ((searchValue != null) && searchValue.equals(currId)))
         {
           return currIndex;
         }
       }            
     }
     
     // didn't find it
     return -1;
   }

  

Retrieve from the UIComponent corresponding to this tag handler the list of all child component ids created by UIComponentTag instances the previous time this tree was rendered. Compare it to the list of children created during this page processing pass, and remove all children present on the old list but not in the new list. Save the list as a UIComponent attribute so that it gets saved as part of the component's state.

 
   private void removeOldChildren()
   {
     Map<StringObjectattributes = .getAttributes();
     List<StringcurrentComponents = ;
 
     // Get the old list of created component ids and update the current list as a
     // component attribute
     Object oldValue;
     
     if (currentComponents != null)
     {
       oldValue = attributes.put(currentComponents);
        = null;
     }
     else
     {
       oldValue = attributes.remove();
     }
               
     // Remove old children that are no longer present
     if (oldValue != null)
     {
       List<StringoldList = TypedCollections.dynamicallyCastList((List)oldValueString.class);
       
       int oldCount = oldList.size();
       
       if (oldCount > 0)
       {
         if (currentComponents != null)
        {
          int currStartIndex = 0;
            
          for (int oldIndex = 0; oldIndex < oldCountoldIndex++)
          {
            String oldId = oldList.get(oldIndex);
            
            int foundIndex = _indexOfStartingFrom(currentComponentscurrStartIndexoldId);
            
            if (foundIndex != -1)
            {
              currStartIndex = foundIndex + 1;
            }
            else
            {
              UIComponent child = .findComponent(oldId);
              // if a component is marked transient, it would have
              // been already removed from the child list, but the
              // oldList would still have it.  In addition, the component
              // might have manually been removed.  So, if findComponent
              // isn't successful, don't call remove child (it will NPE)
              if ( child != null)
              {
                .getChildren().remove(child);
              }
            }
          }
        }
        else
        {
          List<UIComponentchildren = .getChildren();
          
          // All old components need to be removed
          for (String oldId : oldList)
          {
            UIComponent child = .findComponent(oldId);
            if (child != null)
            {
              children.remove(child);
            }            
          }
        }
      }
    }
  }


  

Retrieve from the UIComponent corresponding to this tag handler the list of all facet names created by UIComponentTag instances the previous time this tree was rendered. Compare it to the list of facets created during this page processing pass, and remove all facets present on the old list but not in the new list. Save the list as a UIComponent attribute so that it gets saved as part of the component's state.

  private void removeOldFacets()
  {
    Map<StringObjectattributes = .getAttributes();
    List<StringcurrentComponents = ;
    // Get the old list of created component ids and update the current list as a
    // component attribute
    Object oldValue;
    
    if (currentComponents != null)
    {
      oldValue = attributes.put(currentComponents);
       = null;
    }
    else
    {
      oldValue = attributes.remove();
    }
              
    // Remove old children that are no longer present
    if (oldValue != null)
    {
      List<StringoldList = TypedCollections.dynamicallyCastList((List)oldValueString.class);
      int oldCount = oldList.size();
      
      if (oldCount > 0)
      {
        if (currentComponents != null)
        {
          int currStartIndex = 0;
            
          for (int oldIndex = 0; oldIndex < oldCountoldIndex++)
          {
            String oldId = oldList.get(oldIndex);
            
            int foundIndex = _indexOfStartingFrom(currentComponentscurrStartIndexoldId);
            
            if (foundIndex != -1)
            {
              currStartIndex = foundIndex + 1;
            }
            else
            {
              .getFacets().remove(oldId);
            }
          }
        }
        else
        {
          Map<StringUIComponentfacets = .getFacets();
          
          // All old facets need to be removed
          for (String oldId : oldList)
          {
            facets.remove(oldId);
          }
        }
      }
    }
  }
    //
    // Methods to support content interweaving
    //

    

Create a transient UIOutput component from the body content, of this tag instance or return null if there is no body content, the body content is whitespace, or the body content is a comment.

        UIOutput verbatim = null;
        String bodyContentString;
        String trimString;
        if (null !=  &&
             null != (bodyContentString = .getString()) &&
             0 < (trimString = .getString().trim()).length()) {
            if (!(trimString.startsWith("<!--") &&
                 trimString.endsWith("-->"))) {
                verbatim = createVerbatimComponent();
                verbatim.setValue(bodyContentString);
                .clearBody();
            } else {
                StringBuilder content = new StringBuilder(trimString.length());
                int sIdx = trimString.indexOf("<!--");
                int eIdx = trimString.indexOf("-->"sIdx);
                while (sIdx >= 0 && eIdx >= 0) {
                    if (sIdx == 0) {
                        trimString = trimString.substring(eIdx + 3);
                    } else {
                        content.append(trimString.substring(0, sIdx));
                        trimString = trimString.substring(eIdx + 3);
                    }
                    sIdx = trimString.indexOf("<!--");
                    eIdx = trimString.indexOf("-->"sIdx);
                }
                content.append(trimString);
                String result = content.toString();
                if (result.trim().length() > 0) {
                    verbatim = createVerbatimComponent();
                    verbatim.setValue(content.toString());
                }
                .clearBody();
            }
        }
        return verbatim;
    }

    

Use the Application instance to create a new component with the following characteristics.

componentType is javax.faces.HtmlOutputText.

transient is true.

escape is false.

id is FacesContext.getViewRoot().createUniqueId()

    protected UIOutput createVerbatimComponent() {
	assert(null != getFacesContext());
	UIOutput verbatim;
	verbatim = (UIOutput)
	    application.createComponent("javax.faces.HtmlOutputText");
	verbatim.setTransient(true);
	verbatim.getAttributes().put("escape".);
	return verbatim;
    }

    

Add verbatim as a sibling of component in component in the parent's child list. verbatim is added to the list at the position immediatly preceding component.

    protected void addVerbatimBeforeComponent(
          UIComponentClassicTagBase parentTag,
          UIComponent verbatim,
          UIComponent component) {
        UIComponent parent = component.getParent();
        if (null == parent) {
            return;
        }
        List<UIComponentchildren = parent.getChildren();
        // EDGE CASE:
            // Consider CASE 1 or 2 where the component is provided via a
            // component binding in session or application scope.
            // The automatically created UIOuput instances for the template text
            // will already be present.  Check the JSP_CREATED_COMPONENT_IDS attribute,
            // if present and the number of created components is the same
            // as the number of children replace at a -1 offset from the current
            // value of indexOfComponentInParent, otherwise, call add()
        List createdIds = (List)
              parent.getAttributes().get();
        int indexOfComponentInParent = children.indexOf(component);
        boolean replace =
              (indexOfComponentInParent > 0 && createdIds != null &&
              createdIds.size() == children.size());
        if (replace) {
            UIComponent oldVerbatim = children.get(indexOfComponentInParent - 1);
            if (oldVerbatim instanceof UIOutput && oldVerbatim.isTransient()) {
                children.set((indexOfComponentInParent - 1), verbatim);
            } else {
                children.add(indexOfComponentInParentverbatim);
            }
        } else {
            children.add(indexOfComponentInParentverbatim);
        }
        parentTag.addChild(verbatim);
    }

    

Add verbatim as a sibling of component in component in the parent's child list. verbatim is added to the list at the position immediatly following component.

    protected void addVerbatimAfterComponent(UIComponentClassicTagBase parentTag,
					   UIComponent verbatim,
					   UIComponent component) {
	int indexOfComponentInParent;
	UIComponent parent = component.getParent();
	// invert the order of this if and the assignment below.  Since this line is
	// here, it appears an early return is acceptable/desired if parent is null,
	// and, if it is null, we should probably check for that before we try to
	// access it.  2006-03-15 jdl
	if (null == parent) {
	    return;
	List<UIComponentchildren = parent.getChildren();
	indexOfComponentInParent = children.indexOf(component);
	if (children.size() - 1 == indexOfComponentInParent) {
	    children.add(verbatim);
	else {
	    children.add(indexOfComponentInParent + 1, verbatim);
	parentTag.addChild(verbatim);
    }
    // ------------------------------------------------------------ Tag Methods

    

Perform any processing necessary to find (or create) the UIComponent instance in the view corresponding to this tag instance in the page and, if and only if a component was created, insert it into the tree at the proper location as expected by the page author. Secondarily, cause a transient UIOutput component to be created and placed in the tree before the UIComponent instance for this tag. The value of this UIOutput component must include anything covered by CASE 1 or CASE 2 in the class description.

The default implementation, which is intended to be sufficient for most components, implements this secondary requirement by calling getParentUIComponentClassicTagBase, and calling createVerbatimComponentFromBodyContent on the result. It then adds the returned component to the tree before the actual component for this tag instance instance by calling addVerbatimBeforeComponent.

Before returning, the component is pushed onto the component stack for this response to enable the getParentUIComponentClassicTagBase method to work properly.

The flag value to be returned is acquired by calling the getDoStartValue() method, which tag subclasses may override if they do not want the default value.

Throws:
JspException if an error occurs
    public int doStartTag() throws JspException {
	// make sure that these ivars are reset at the beginning of the
	// lifecycle for this tag.
	UIComponent verbatim = null;
         = getFacesContext();
	if (null == ) {
	    // PENDING(edburns): I18N
	    throw new JspException("Can't find FacesContext");
        getContextMap();
        assert(null != );
        List list = (List.get();
        if (list != null) {
             = ((UIComponentClassicTagBaselist.get(list.size() - 1));
        } else {
             = null;
        }
        Map<String,UIComponentTagBasecomponentIds;
        // If we're not inside of a facet, and if we are inside of a
        // rendersChildren==true component, stuff any template text or
        // custom tag output into a transient component.
        if (null == getFacetName() &&
            null != ) {
            Tag p = this.getParent();
            // If we're not inside a JSP tag or we're not inside
            // a UIComponentTag flush the buffer
            if (null == p || !(p instanceof UIComponentTagBase)) {
                JspWriter out = .getOut();
                if (!(out instanceof BodyContent)) {
                    try {
                        out.flush();
                    }
                    catch (IOException ioe) {
                        throw new JspException(ioe);
                    }
                }
            }
            verbatim = .createVerbatimComponentFromBodyContent();
        }
        // Locate the UIComponent associated with this UIComponentTag,
        // creating one if necessary
         = findComponent();
	// if we have a verbatim component, add it after this component.
	if (null != verbatim) {
				       verbatim);
        Object tagInstance = null;
        String clientId = null;
        if ( instanceof NamingContainer || ( == null)) {
             = new HashMap<StringMap<StringUIComponentTagBase>>();
        }
        if (this. != null) {
            clientId = getId();
            UIComponentClassicTagBase temp = (UIComponentClassicTagBase)
                getParentNamingContainerTag().getNamingContainerChildIds().get(clientId);
            // According to the JavaDocs for JspIdConsumer tag handlers
            // that implement this interface are not to be pooled, however
            // due to a bug in Jasper this is not the case.
            // Because of this, two tags with the same ID within the same
            // naming container will not be detected as duplicates.  So
            // in order to ensure we detect it, if the instance is the same,
            // verify the JSP IDs are different.  If they are, then continue,
            // if they aren't, then we're dealing with EVAL_BODY_AGAIN (see
            // below)
            //noinspection ObjectEquality
            if (temp == this
                 && !this.getJspId().equals(temp.getJspId())) {
                tagInstance = this;
            } else if (temp != null
                         && temp != this
                         && this.getJspId().equals(temp.getJspId())) {
                // new instance, same JSP ID - this is the EVAL_BODY_AGAIN case.
                tagInstance = temp;
            }
        }
        // If we have a tag instance, then, most likely, a tag handler
        // returned EVAL_BODY_AGAIN somewhere.  Make sure the instance
        // returned is the same as the current instance and if this is the case,
        // do not perform ID validation as it has already been done.
        if (tagInstance == null) {
            // only check for id uniqueness if the author has manually given
            // us an id.
            if (null != this.) {
                // assert component ID uniqueness
                if (clientId != null) {
                    if (getParentNamingContainerTag().getNamingContainerChildIds().containsKey(clientId)) {
                        // PENDING i18n
                        StringWriter writer = new StringWriter(128);
                        printTree(.getViewRoot(), clientIdwriter, 0);
                        String msg = "Duplicate component id: '"
                                     + clientId
                                     + "', first used in tag: '"
                                     + getParentNamingContainerTag().getNamingContainerChildIds().get(clientId).getClass().getName()
                                     + "'\n"
                                     + writer.toString();
                        throw new JspException(new IllegalStateException(msg));
                    } else {
                        getParentNamingContainerTag().getNamingContainerChildIds().put(clientIdthis);
                    }
                }
            }
            // Add to parent's list of created components or facets if needed
            if ( != null) {
                if (getFacetName() == null) {
                    .addChild();
                } else {
                    .addFacet(getFacetName());
                }
            }
        }
	// Rendering is deferred until after the tree is completely
	// created
        // Return the appropriate control value
        return (getDoStartValue());
    }
    private Map<StringObjectgetContextMap(FacesContext context) {
        if (null == ) {
            Map<StringObjectrequestMap = context.getExternalContext().getRequestMap();
             = (Map<StringObject>) requestMap.get();
            if (null == ) {
                 = new HashMap<StringObject>(5);
                requestMap.put();
            }
        }
        return ;
    }
    private static Map<StringObject_getContextMap(FacesContext context) {
        Map<StringObjectrMap = context.getExternalContext().getRequestMap();
        return (Map<String,Object>) rMap.get();
    }
    private void releaseContextMap(FacesContext context) {
        Map<StringObjectrequestMap = context.getExternalContext().getRequestMap();
        if (null != ) {
            .clear();
        }
        requestMap.remove();
    }


    

Perform any processing necessary to handle the content implications of CASE 3 in the class description.

The default implementation, which is intended to be sufficient for most components, calls createVerbatimComponentFromBodyContent on this instance and adds it as a child of the component for this tag's component at the end of the child list. In addition, the following housekeeping steps are taken.

  • Retrieve from the UIComponent the set of component ids of child components created by UIComponentTag instances the last time this page was processed (if any). Compare it to the list of children created during this page processing pass, and remove all children present in the old list but not the new. Save the new list as a component attribute so that it gets saved as part of the component's state.
  • Retrieve from the UIComponent the set of facet names of facets created by UIComponentTag instances the last time this page was processed (if any). Compare it to the list of facets created during this page processing pass, and remove all facets present in the old list but not the new. Save the new list as a component attribute so that it gets saved as part of the component's state.
  • Release all references to the component, and pop it from the component stack for this response, removing the stack if this was the outermost component.

The flag value to be returned is acquired by calling the getDoEndValue() method, which tag subclasses may override if they do not want the default value.

Throws:
JspException if an error occurs
    public int doEndTag() throws JspException
    {
      // Remove old children and facets as needed
      removeOldChildren();
      removeOldFacets();
      //If we are at the end tag of a NamingContainer component, reset the Map of ids
      // for the NamingContainer tag.
      if ( != null) {
           = null;
      }
      // Render the children (if needed) and  end of the component
      // associated with this tag
      try
      {
	      UIComponent verbatim;
                                                                                 );
	      if (null != (verbatim = this.createVerbatimComponentFromBodyContent()))
        {
          .getChildren().add(verbatim);
          
		      if (null != parentTag) {
		        parentTag.addChild(verbatim);
		    }
	    }
	    // else, we don't render rendersChildren==true
	    // components here
        } catch (Throwable e) {
            throw new JspException(e);
        } finally {
             = null;
             = null;
        }
        // Return the appropriate control value
	this.release();
        return (getDoEndValue());
    }

    

Release any resources allocated during the execution of this tag handler.

    public void release() {
        this. = null;
        this. = null;
        this. = null;
        this. = false;
	this. = null;
        this. = false;
       = 0;
    }
    // -------------------------------------------- Support methods for BodyTag

    

Return the flag value that should be returned from the doAfterBody() method when it is called. Subclasses may override this method to return the appropriate value.

    protected int getDoAfterBodyValue() throws JspException {
        return ();
    }
    // -------------------------------------------------------- BodyTag Methods

    

Set the bodyContent for this tag handler. This method is invoked by the JSP page implementation object at most once per action invocation, before doInitiBody(). This method will not be invoked for empty tags or for non-empty tags whose doStartTag() method returns SKIP_BODY or EVAL_BODY_INCLUDE.

Parameters:
bodyContent The new BodyContent for this tag
    public void setBodyContent(BodyContent bodyContent) {
        this. = bodyContent;
    }

    

Get the JspWriter from our BodyContent.

    public JspWriter getPreviousOut() {
        return (this..getEnclosingWriter());
    }
    public BodyContent getBodyContent() {
        return (this.);
    }



    

Prepare for evaluation of the body. This method is invoked by the JSP page implementation object after setBodyContent() and before the first time the body is to be evaluated