Package javax.faces.webapp

Source Code of javax.faces.webapp.UIComponentTag

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package javax.faces.webapp;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.context.ExternalContext;
import javax.faces.el.ValueBinding;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;
import java.io.IOException;
import java.util.*;

/**
* Base class for all JSP tags that represent a JSF UIComponent.
* <p>
* <i>Disclaimer</i>: The official definition for the behaviour of
* this class is the JSF specification but for legal reasons the
* specification cannot be replicated here. Any javadoc present on this
* class therefore describes the current implementation rather than the
* officially required behaviour, though it is believed that this class
* does comply with the specification.
*
* see Javadoc of <a href="http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/index.html">JSF Specification</a> for more.
*
* @author Manfred Geiler (latest modification by $Author: grantsmith $)
* @version $Revision: 472558 $ $Date: 2006-11-08 18:36:53 +0100 (Mi, 08 Nov 2006) $
*/
public abstract class UIComponentTag
        implements Tag
{
    private static final String FORMER_CHILD_IDS_SET_ATTR = UIComponentTag.class.getName() + ".FORMER_CHILD_IDS";
    private static final String FORMER_FACET_NAMES_SET_ATTR = UIComponentTag.class.getName() + ".FORMER_FACET_NAMES";
    private static final String COMPONENT_STACK_ATTR =  UIComponentTag.class.getName() + ".COMPONENT_STACK";

    private static final String UNIQUE_ID_COUNTER_ATTR = UIComponentTag.class.getName() + ".UNIQUE_ID_COUNTER";

    protected PageContext pageContext = null;
    private Tag _parent = null;

    //tag attributes
    private String _binding = null;
    private String _id = null;
    private String _rendered = null;

    private FacesContext _facesContext = null;
    private UIComponent _componentInstance = null;
    private boolean _created = false;
    private Boolean _suppressed = null;
    private ResponseWriter _writer = null;
    private Set _childrenAdded = null;
    private Set _facetsAdded = null;

    private static Log log = LogFactory.getLog(UIComponentTag.class);


    public UIComponentTag()
    {

    }

    public void release()
    {
        internalRelease();

        //members, that must/need only be reset when there is no more risk, that the container
        //wants to reuse this tag
        pageContext = null;
        _parent = null;

        // Reset tag attribute members. These are reset here rather than in
        // internalRelease because of some Resin-related issue. See commit
        // r166747.
        _binding = null;
        _id = null;
        _rendered = null;
    }


    /**
     * Reset any members that apply to the according component instance and
     * must not be reused if the container wants to reuse this tag instance.
     * This method is called when rendering for this tag is finished
     * ( doEndTag() ) or when released by the container.
     */
    private void internalRelease()
    {
        _facesContext = null;
        _componentInstance = null;
        _created = false;
        _suppressed = null;
        _writer = null;
        _childrenAdded = null;
        _facetsAdded = null;
    }

    /** Setter for common JSF xml attribute "binding". */
    public void setBinding(String binding)
            throws JspException
    {
        if (!isValueReference(binding))
        {
            throw new IllegalArgumentException("not a valid binding: " + binding);
        }
        _binding = binding;
    }

    /** Setter for common JSF xml attribute "id". */
    public void setId(String id)
    {
        _id = id;
    }

    /**
     * Return the id (if any) specified as an xml attribute on this tag.
     */
    protected String getId()
    {
        return _id;
    }

    /** Setter for common JSF xml attribute "rendered". */
    public void setRendered(String rendered)
    {
        _rendered = rendered;
    }

    /**
     * Specify the "component type name" used together with the component's
     * family and the Application object to create a UIComponent instance for
     * this tag. This method is called by other methods in this class, and is
     * intended to be overridden in subclasses to specify the actual component
     * type to be created.
     *
     * @return a registered component type name, never null.
     */
    public abstract String getComponentType();

    /**
     * Return the UIComponent instance associated with this tag.
     * @return a UIComponent, never null.
     */
    public UIComponent getComponentInstance()
    {
        return _componentInstance;
    }

    /**
     * Return true if this tag created the associated UIComponent (rather
     * than locating an existing instance of the UIComponent in the view).
     */
    public boolean getCreated()
    {
        return _created;
    }

    /**
     * Return the nearest JSF tag that encloses this tag.
     */
    public static UIComponentTag getParentUIComponentTag(PageContext pageContext)
    {
        // Question: why not just walk up the _parent chain testing for
        // instanceof UIComponentTag rather than maintaining a separate
        // stack with the pushTag and popTag methods?
        List list = (List)pageContext.getAttribute(COMPONENT_STACK_ATTR,
                                                   PageContext.REQUEST_SCOPE);
        if (list != null)
        {
            return (UIComponentTag)list.get(list.size() - 1);
        }
        return null;
    }

    /** See documentation for pushTag. */
    private void popTag()
    {
        List list = (List)pageContext.getAttribute(COMPONENT_STACK_ATTR,
                                                    PageContext.REQUEST_SCOPE);
        if (list != null)
        {
            int size = list.size();
            list.remove(size -1);
            if (size <= 1)
            {
                pageContext.removeAttribute(COMPONENT_STACK_ATTR,
                                             PageContext.REQUEST_SCOPE);
            }
        }
    }

    /**
     * Push this tag onto the stack of JSP tags seen.
     * <p>
     * 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 find the
     * parent tag that encloses it. Access to the parent tag is used
     * to find the parent UIComponent for the component associated
     * with this tag plus some other uses.
     */
    private void pushTag()
    {
        List list = (List)pageContext.getAttribute(COMPONENT_STACK_ATTR,
                                                    PageContext.REQUEST_SCOPE);
        if (list == null)
        {
            list = new ArrayList();
            pageContext.setAttribute(COMPONENT_STACK_ATTR,
                                      list,
                                      PageContext.REQUEST_SCOPE);
        }
        list.add(this);
    }

    /**
     * Specify the "renderer type name" used together with the current
     * renderKit to get a Renderer instance for the corresponding UIComponent.
     * <p>
     * A JSP tag can return null here to use the default renderer type string.
     * If non-null is returned, then the UIComponent's setRendererType method
     * will be called passing this value, and this will later affect the
     * type of renderer object returned by UIComponent.getRenderer().
     */
    public abstract String getRendererType();

    /**
     * Return true if the specified string contains an EL expression.
     * <p>
     * UIComponent properties are often required to be value-binding
     * expressions; this method allows code to check whether that is
     * the case or not.
     */
    public static boolean isValueReference(String value)
    {
        if (value == null) throw new NullPointerException("value");

        int start = value.indexOf("#{");
        if (start < 0) return false;

        int end = value.lastIndexOf('}');
        return (end >=0 && start < end);
    }

    /**
     * Standard method invoked by the JSP framework to inform this tag
     * of the PageContext associated with the jsp page currently being
     * processed.
     */
    public void setPageContext(PageContext pageContext)
    {
        this.pageContext = pageContext;
    }

    /**
     * Returns the enclosing JSP tag object. Note that this is not
     * necessarily a JSF tag.
     */
    public Tag getParent()
    {
        return _parent;
    }

    /**
     * Standard method invoked by the JSP framework to inform this tag
     * of the enclosing JSP tag object.
     */
    public void setParent(Tag parent)
    {
        _parent = parent;
    }

    /**
     * Invoked by the standard jsp processing mechanism when the opening
     * tag of a JSF component element is found.
     * <p>
     * The UIComponent associated with this tag is created (if the view
     * doesn't exist) or located if the view is being re-rendered. If
     * the component is not "suppressed" then its encodeBegin method is
     * called (see method isSuppressed). Note also that method
     * encodeBegin is <i>not</i> called for components for which
     * getRendersChildren returns true; that occurs only in doEndTag.
     */
    public int doStartTag()
            throws JspException
    {
        setupResponseWriter();
        FacesContext facesContext = getFacesContext();
        UIComponent component = findComponent(facesContext);
        if (!component.getRendersChildren() && !isSuppressed())
        {
            try
            {
                encodeBegin();
                _writer.flush();
            }
            catch (IOException e)
            {
                throw new JspException(e.getMessage(), e);
            }
        }
        pushTag();
        return getDoStartValue();
    }

    /**
     * Invoked by the standard jsp processing mechanism when the closing
     * tag of a JSF component element is found.
     * <p>
     * When the view is being re-rendered, any former children of this tag's
     * corresponding component which do not have corresponding tags
     * as children of this tag are removed from the view. This isn't likely
     * to be a common occurrence: wrapping JSF tags in JSTL tag "c:if" is
     * one possible cause. Programmatically created components are not affected
     * by this.
     * <p>
     * If the corresponding component returns true from getRendersChildren
     * then its encodeBegin and encodeChildren methods are called here.
     * <p>
     * The component's encodeEnd method is called provided the component
     * is not "suppressed".
     */
    public int doEndTag()
            throws JspException
    {
        popTag();
        UIComponent component = getComponentInstance();
        removeFormerChildren(component);
        removeFormerFacets(component);

        try
        {
            if (!isSuppressed())
            {
                if (component.getRendersChildren())
                {
                    encodeBegin();
                    encodeChildren();
                }
                encodeEnd();
            }
        }
        catch (IOException e)
        {
            throw new JspException(e.getMessage(), e);
        }

        int retValue = getDoEndValue();
        internalRelease();
        return retValue;
    }

    /**
     * Remove any child components of the associated components which do not
     * have corresponding tags as children of this tag. This only happens
     * when a view is being re-rendered and there are components in the view
     * tree which don't have corresponding JSP tags. Wrapping JSF tags in
     * JSTL "c:if" statements is one way this can happen.
     * <br />
     * Attention: programmatically added components are are not affected by this:
     * they will not be on the old list of created components nor on the new list
     * of created components, so nothing will happen to them.
     */
    private void removeFormerChildren(UIComponent component)
    {
        Set formerChildIdsSet = (Set)component.getAttributes().get(FORMER_CHILD_IDS_SET_ATTR);
        if (formerChildIdsSet != null)
        {
            for (Iterator iterator = formerChildIdsSet.iterator(); iterator.hasNext();)
            {
                String childId = (String)iterator.next();
                if (_childrenAdded == null || !_childrenAdded.contains(childId))
                {
                    UIComponent childToRemove = component.findComponent(childId);
                    if (childToRemove != null)
                    {
                        component.getChildren().remove(childToRemove);
                    }
                }
            }
            if (_childrenAdded == null)
            {
                component.getAttributes().remove(FORMER_CHILD_IDS_SET_ATTR);
            }
            else
            {
                component.getAttributes().put(FORMER_CHILD_IDS_SET_ATTR, _childrenAdded);
            }
        }
        else
        {
            if (_childrenAdded != null)
            {
                component.getAttributes().put(FORMER_CHILD_IDS_SET_ATTR, _childrenAdded);
            }
        }
    }

    /** See removeFormerChildren. */
    private void removeFormerFacets(UIComponent component)
    {
        Set formerFacetNamesSet = (Set)component.getAttributes().get(FORMER_FACET_NAMES_SET_ATTR);
        if (formerFacetNamesSet != null)
        {
            for (Iterator iterator = formerFacetNamesSet.iterator(); iterator.hasNext();)
            {
                String facetName = (String)iterator.next();
                if (_facetsAdded == null || !_facetsAdded.contains(facetName))
                {
                    component.getFacets().remove(facetName);
                }
            }
            if (_facetsAdded == null)
            {
                component.getAttributes().remove(FORMER_FACET_NAMES_SET_ATTR);
            }
            else
            {
                component.getAttributes().put(FORMER_FACET_NAMES_SET_ATTR, _facetsAdded);
            }
        }
        else
        {
            if (_facetsAdded != null)
            {
                component.getAttributes().put(FORMER_FACET_NAMES_SET_ATTR, _facetsAdded);
            }
        }
    }

    /**
     * Invoke encodeBegin on the associated UIComponent. Subclasses can
     * override this method to perform custom processing before or after
     * the UIComponent method invocation.
     */
    protected void encodeBegin()
            throws IOException
    {
        if(log.isDebugEnabled())
            log.debug("Entered encodeBegin for client-Id: "+_componentInstance.getClientId(getFacesContext()));
        _componentInstance.encodeBegin(getFacesContext());
        if(log.isDebugEnabled())
            log.debug("Exited encodeBegin");
    }

    /**
     * Invoke encodeChildren on the associated UIComponent. Subclasses can
     * override this method to perform custom processing before or after
     * the UIComponent method invocation. This is only invoked for components
     * whose getRendersChildren method returns true.
     */
    protected void encodeChildren()
            throws IOException
    {
        if(log.isDebugEnabled())
            log.debug("Entered encodeChildren for client-Id: "+_componentInstance.getClientId(getFacesContext()));
        _componentInstance.encodeChildren(getFacesContext());
        if(log.isDebugEnabled())
            log.debug("Exited encodeChildren for client-Id: "+_componentInstance.getClientId(getFacesContext()));
    }

    /**
     * Invoke encodeEnd on the associated UIComponent. Subclasses can override this
     * method to perform custom processing before or after the UIComponent method
     * invocation.
     */
    protected void encodeEnd()
            throws IOException
    {
        if(log.isDebugEnabled())
            log.debug("Entered encodeEnd for client-Id: "+_componentInstance.getClientId(getFacesContext()));
        _componentInstance.encodeEnd(getFacesContext());
        if(log.isDebugEnabled())
            log.debug("Exited encodeEnd for client-Id: "+_componentInstance.getClientId(getFacesContext()));

    }

    /**
     * Return the corresponding UIComponent for this tag, creating it
     * if necessary.
     * <p>
     * If this is not the first time this method has been called, then
     * return the cached component instance found last time.
     * <p>
     * If this is not the first time this view has been seen, then
     * locate the existing component using the id attribute assigned
     * to this tag and return it. Note that this is simple for
     * components with user-assigned ids. For components with
     * generated ids, the "reattachment" relies on the fact that
     * UIViewRoot will generate the same id values for tags in
     * this page as it did when first generating the view. For this
     * reason all JSF tags within a JSTL "c:if" are required to have
     * explicitly-assigned ids.
     * <p>
     * Otherwise create the component, populate its properties from
     * the xml attributes on this JSP tag and attach it to its parent.
     * <p>
     * When a component is found or created the parent JSP tag is also
     * told that the component has been "seen". When the parent tag
     * ends it will delete any components which were in the view
     * previously but have not been seen this time; see doEndTag for
     * more details.
     */
    protected UIComponent findComponent(FacesContext context)
            throws JspException
    {
        if (_componentInstance != null) return _componentInstance;
        UIComponentTag parentTag = getParentUIComponentTag(pageContext);
        if (parentTag == null)
        {
            //This is the root
            _componentInstance = context.getViewRoot();
            setProperties(_componentInstance);
            return _componentInstance;
        }

        UIComponent parent = parentTag.getComponentInstance();
        //TODO: what if parent == null?
        if (parent == null) throw new IllegalStateException("parent is null?");

        String facetName = getFacetName();
        if (facetName != null)
        {
            //Facet
            String id = getOrCreateUniqueId(context);
            _componentInstance = parent.getFacet(facetName);
            if (_componentInstance == null)
            {
              _componentInstance = createComponentInstance(context, id);
                setProperties(_componentInstance);
                parent.getFacets().put(facetName, _componentInstance);
            }
            else
            {
              if (checkFacetNameOnParentExists(parentTag, facetName))
              {
                throw new IllegalStateException("facet '" + facetName + "' already has a child associated. current associated component id: "
                  + _componentInstance.getClientId(context) + " class: " + _componentInstance.getClass().getName());
              }
            }
           
            addFacetNameToParentTag(parentTag, facetName);
            return _componentInstance;
        }
        else
        {
            //Child
            //
            // Note that setProperties is called only when we create the
            // component; on later passes, the attributes defined on the
            // JSP tag are set on this Tag object, but then completely
            // ignored.

            String id = getOrCreateUniqueId(context);
           
            // Warn users that this tag is about to find/steal the UIComponent
            // that has already been created for a sibling tag with the same id value .
            // _childrenAdded is a Set, and we will stomp over a past id when calling
            // addChildIdToParentTag.
            //
            // we throw an exception here - RI issues a warning.
            if(parentTag._childrenAdded != null && parentTag._childrenAdded.contains(id))
            {
                throw new FacesException("There is more than one JSF tag with id : " + id+" for parent component with id : '"+parent.getId()+"'");
            }
           
            _componentInstance = findComponent(parent,id);
            if (_componentInstance == null)
            {
                _componentInstance = createComponentInstance(context, id);
                setProperties(_componentInstance);
                int index = getAddedChildrenCount(parentTag);
                List children = parent.getChildren();
                if (index <= children.size())
                {
                    children.add(index, _componentInstance);
                }
                else
                {
                    throw new FacesException("cannot add component with id '" +
                            _componentInstance.getId() + " to its parent component with id : '"+parent.getId()+"' and path '"+
                            getPathToComponent(parent)+"'at position :"+index+" in list of children. "+
                            "This might be a problem due to a duplicate id in a previously added component,"+
                            "if this is the case, the problematic id might be one of : "+printSet(parentTag._childrenAdded));
                }
            }
            addChildIdToParentTag(parentTag, id);
            return _componentInstance;
        }
    }

    private UIComponent findComponent(UIComponent parent, String id)
    {
        List li = parent.getChildren();

        for (int i = 0; i < li.size(); i++)
        {
            UIComponent uiComponent = (UIComponent) li.get(i);
            if(uiComponent.getId()!=null && uiComponent.getId().equals(id))
            {
                return uiComponent;
            }
        }

        return null;
    }

    /**
     * Utility method for creating diagnostic output.
     */
    private String printSet(Set childrenAdded)
    {
        StringBuffer buf = new StringBuffer();

        if(childrenAdded!=null)
        {
            Iterator it = childrenAdded.iterator();

            while (it.hasNext())
            {
                Object obj =  it.next();
                buf.append(obj);

                if(it.hasNext())
                    buf.append(",");
            }
        }
        return buf.toString();
    }


    private String getOrCreateUniqueId(FacesContext context)
    {
        String id = getId();
        if (id != null)
        {
            return id;
        }
        else
        {
            //we've been calling
            //return context.getViewRoot().createUniqueId(); - don't want that anymore
            Long currentCounter = (Long) context.getExternalContext().getRequestMap().get(UNIQUE_ID_COUNTER_ATTR);
            long lCurrentCounter = 0;

            if(currentCounter!=null)
            {
                lCurrentCounter = currentCounter.longValue();
            }

            StringBuffer retValue = new StringBuffer(UIViewRoot.UNIQUE_ID_PREFIX);
            retValue.append("Jsp");
            retValue.append(lCurrentCounter);

            lCurrentCounter++;

            context.getExternalContext().getRequestMap().put(UNIQUE_ID_COUNTER_ATTR,new Long(lCurrentCounter));

            ExternalContext extCtx = FacesContext.getCurrentInstance().getExternalContext();
            return extCtx.encodeNamespace(retValue.toString());
        }
    }

    /**
     * Create a UIComponent. Abstract method getComponentType is invoked to
     * determine the actual type name for the component to be created.
     *
     * If this tag has a "binding" attribute, then that is immediately
     * evaluated to store the created component in the specified property.
     */
    private UIComponent createComponentInstance(FacesContext context, String id)
    {
        String componentType = getComponentType();
        if (componentType == null)
        {
            throw new NullPointerException("componentType");
        }

        if (_binding != null)
        {
            Application application = context.getApplication();
            ValueBinding componentBinding = application.createValueBinding(_binding);
            UIComponent component = application.createComponent(componentBinding,
                                                                context,
                                                                componentType);
            component.setId(id);
            component.setValueBinding("binding", componentBinding);
            recurseFacetsAndChildrenForId(component.getFacetsAndChildren(), id + "_", 0);
            _created = true;
            return component;
        }
        else
        {
            UIComponent component = context.getApplication().createComponent(componentType);
            component.setId(id);
            _created = true;
            return component;
        }
    }

    /**
     * Recurse all facets and children and assign them an unique ID if
     * necessary. We must *not* use UIViewRoot#createUniqueId here,
     * because this would affect the order of the created ids upon
     * rerendering the page!
     */
    private int recurseFacetsAndChildrenForId(
            Iterator facetsAndChildren,
            String idPrefix,
            int cnt)
    {
        while (facetsAndChildren.hasNext())
        {
            UIComponent comp = (UIComponent)facetsAndChildren.next();
            if (comp.getId() == null)
            {
                ++cnt;
                comp.setId(idPrefix + cnt);
            }
            cnt = recurseFacetsAndChildrenForId(comp.getFacetsAndChildren(), idPrefix, cnt);
        }
        return cnt;
    }

    /**
     * Notify the enclosing JSP tag of the id of this component's id. The
     * parent tag will later delete any existing view components that were
     * not seen during this rendering phase; see doEndTag for details.
     */
    private void addChildIdToParentTag(UIComponentTag parentTag, String id)
    {
        if (parentTag._childrenAdded == null)
        {
            parentTag._childrenAdded = new HashSet();
        }
        parentTag._childrenAdded.add(id);
    }

    /**
     * check if the facet is already added to the parent
     */
    private boolean checkFacetNameOnParentExists(UIComponentTag parentTag, String facetName)
    {
        return parentTag._facetsAdded != null && parentTag._facetsAdded.contains(facetName);
    }
   
    /**
     * Notify the enclosing JSP tag of the id of this facet's id. The parent
     * tag will later delete any existing view facets that were not seen
     * during this rendering phase; see doEndTag for details.
     */
    private void addFacetNameToParentTag(UIComponentTag parentTag, String facetName)
    {
        if (parentTag._facetsAdded == null)
        {
            parentTag._facetsAdded = new HashSet();
        }
        parentTag._facetsAdded.add(facetName);
    }

    private int getAddedChildrenCount(UIComponentTag parentTag)
    {
        return parentTag._childrenAdded != null ?
               parentTag._childrenAdded.size() :
               0;
    }

    /**
     * Get the value to be returned by the doStartTag method to the
     * JSP framework. Subclasses which wish to use the inherited
     * doStartTag but control whether the tag is permitted to contain
     * nested tags or not can just override this method to return
     * Tag.SOME_CONSTANT.
     *
     * @return Tag.EVAL_BODY_INCLUDE
     */
    protected int getDoStartValue()
            throws JspException
    {
        return Tag.EVAL_BODY_INCLUDE;
    }

    /**
     * Get the value to be returned by the doEndTag method to the
     * JSP framework. Subclasses which wish to use the inherited
     * doEndTag but control whether the tag is permitted to contain
     * nested tags or not can just override this method to return
     * Tag.SOME_CONSTANT.
     *
     * @return Tag.EVAL_PAGE
     */
    protected int getDoEndValue()
            throws JspException
    {
        return Tag.EVAL_PAGE;
    }

    protected FacesContext getFacesContext()
    {
        if (_facesContext == null)
        {
            _facesContext = FacesContext.getCurrentInstance();
        }
        return _facesContext;
    }


    private boolean isFacet()
    {
        return _parent != null && _parent instanceof FacetTag;
    }

    protected String getFacetName()
    {
        return isFacet() ? ((FacetTag)_parent).getName() : null;
    }

    /**
     * Determine whether this component renders itself. A component
     * is "suppressed" when it is either not rendered, or when it is
     * rendered by its parent component at a time of the parent's choosing.
     */
    protected boolean isSuppressed()
    {
        if (_suppressed == null)
        {
            // we haven't called this method before, so determine the suppressed
            // value and cache it for later calls to this method.

            if (isFacet())
            {
                // facets are always rendered by their parents --> suppressed
                _suppressed = Boolean.TRUE;
                return true;
            }

            UIComponent component = getComponentInstance();

            // Does any parent render its children?
            // (We must determine this first, before calling any isRendered method
            //  because rendered properties might reference a data var of a nesting UIData,
            //  which is not set at this time, and would cause a VariableResolver error!)
            UIComponent parent = component.getParent();
            while (parent != null)
            {
                if (parent.getRendersChildren())
                {
                    //Yes, parent found, that renders children --> suppressed
                    _suppressed = Boolean.TRUE;
                    return true;
                }
                parent = parent.getParent();
            }

            // does component or any parent has a false rendered attribute?
            while (component != null)
            {
                if (!component.isRendered())
                {
                    //Yes, component or any parent must not be rendered --> suppressed
                    _suppressed = Boolean.TRUE;
                    return true;
                }
                component = component.getParent();
            }

            // else --> not suppressed
            _suppressed = Boolean.FALSE;
        }
        return _suppressed.booleanValue();
    }

    protected void setProperties(UIComponent component)
    {
        if (getRendererType() != null)
        {
            _componentInstance.setRendererType(getRendererType());
        }

        if (_rendered != null)
        {
            if (isValueReference(_rendered))
            {
                ValueBinding vb = getFacesContext().getApplication().createValueBinding(_rendered);
                component.setValueBinding("rendered", vb);
            } else
            {
                boolean b = Boolean.valueOf(_rendered).booleanValue();
                component.setRendered(b);
            }
        }
    }

    protected void setupResponseWriter()
    {
        FacesContext facesContext = getFacesContext();

        if(facesContext == null)
        {
            throw new FacesException("Faces context not found. getResponseWriter will fail. "+
                    "Check if the FacesServlet has been initialized at all in your web.xml configuration file"+
                    "and if you are accessing your jsf-pages through the correct mapping. E.g.: if your FacesServlet is mapped to "+
                    " *.jsf (with the <servlet-mapping>-element), you need to access your pages as 'sample.jsf'. If you tried to access 'sample.jsp', you'd get this error-message."                   
                    );
        }

        _writer = facesContext.getResponseWriter();
        if (_writer == null)
        {
            RenderKitFactory renderFactory = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
            RenderKit renderKit = renderFactory.getRenderKit(facesContext,
                                                             facesContext.getViewRoot().getRenderKitId());

            _writer = renderKit.createResponseWriter(new _PageContextOutWriter(pageContext),
                                                     null /*Default: get the allowed content-types from the accept-header*/,
                                                     pageContext.getRequest().getCharacterEncoding());
            facesContext.setResponseWriter(_writer);
        }
    }

    /** Generate diagnostic output. */
    private String getPathToComponent(UIComponent component)
    {
        StringBuffer buf = new StringBuffer();

        if(component == null)
        {
            buf.append("{Component-Path : ");
            buf.append("[null]}");
            return buf.toString();
        }

        getPathToComponent(component,buf);

        buf.insert(0,"{Component-Path : ");
        buf.append("}");

        return buf.toString();
    }

    /** Generate diagnostic output. */
    private static void getPathToComponent(UIComponent component, StringBuffer buf)
    {
        if(component == null)
            return;

        StringBuffer intBuf = new StringBuffer();

        intBuf.append("[Class: ");
        intBuf.append(component.getClass().getName());
        if(component instanceof UIViewRoot)
        {
            intBuf.append(",ViewId: ");
            intBuf.append(((UIViewRoot) component).getViewId());
        }
        else
        {
            intBuf.append(",Id: ");
            intBuf.append(component.getId());
        }
        intBuf.append("]");

        buf.insert(0,intBuf);

        getPathToComponent(component.getParent(),buf);
    }

}
TOP

Related Classes of javax.faces.webapp.UIComponentTag

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.