Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package jakarta.faces.webapp;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.RandomAccess;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import jakarta.faces.FacesException;
import jakarta.faces.application.Application;
import jakarta.faces.component.NamingContainer;
import jakarta.faces.component.UIComponent;
import jakarta.faces.component.UIOutput;
import jakarta.faces.component.UIViewRoot;
import jakarta.faces.context.FacesContext;
import jakarta.servlet.jsp.JspException;
import jakarta.servlet.jsp.JspWriter;
import jakarta.servlet.jsp.PageContext;
import jakarta.servlet.jsp.tagext.BodyContent;
import jakarta.servlet.jsp.tagext.BodyTag;
import jakarta.servlet.jsp.tagext.JspIdConsumer;
import jakarta.servlet.jsp.tagext.Tag;
/**
*
* UIComponentTagBase is the base class for all Jakarta Server Pages tags that use the
* "classic" Jakarta Server Pages tag interface that correspond to a {@link jakarta.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.
*
*
*
* {@link UIComponentTag} extends UIComponentClassicTagBase to add support for properties that conform to
* the Faces 1.1 Expression Language.
*
*
*
* {@link UIComponentELTag} extends UIComponentClassicTagBase class to add support for properties that
* conform to the Expression Language API.
*
*
*
* The default implementation allows the proper interweaving of template text, non-Faces Jakarta Server Pages 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.
*
* 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).
*
*
*
*/
public abstract class UIComponentClassicTagBase extends UIComponentTagBase implements JspIdConsumer, BodyTag {
// ------------------------------------------------------ Manifest Constants
/**
*
* The facesContext scope attribute under which a component tag stack for the current facesContext will be maintained.
*
*/
private static final String COMPONENT_TAG_STACK_ATTR = "jakarta.faces.webapp.COMPONENT_TAG_STACK";
/**
*
* The {@link 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 = "jakarta.faces.webapp.COMPONENT_IDS";
/**
*
* The {@link 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 = "jakarta.faces.webapp.FACET_NAMES";
/**
*
* The attribute name under which we will store all {@link UIComponent} IDs of the current translation unit.
*
*/
private static final String GLOBAL_ID_VIEW = "jakarta.faces.webapp.GLOBAL_ID_VIEW";
/**
*
* The attribute name under which we will store the {@link FacesContext} for this request.
*
*/
private static final String CURRENT_FACES_CONTEXT = "jakarta.faces.webapp.CURRENT_FACES_CONTEXT";
/**
*
* The attribute name under which we will store the {@link UIViewRoot} for this request.
*
*/
private static final String CURRENT_VIEW_ROOT = "jakarta.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 = UIViewRoot.UNIQUE_ID_PREFIX + '_';
/**
* Used to store the previousJspId Map in facesContextScope
*/
private static final String PREVIOUS_JSP_ID_SET = "jakarta.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 JAKARTA_FACES_PAGECONTEXT_MARKER = "jakarta.faces.webapp.PAGECONTEXT_MARKER";
/**
* This is a facesContext scoped attribute which contains an AtomicInteger which we use to increment the
* PageContext count.
*/
private static final String JAKARTA_FACES_PAGECONTEXT_COUNTER = "jakarta.faces.webapp.PAGECONTEXT_COUNTER";
// ------------------------------------------------------ Instance Variables
/**
*
* The Jakarta Server Pages Tag that is the parent of this tag.
*
*/
private Tag parent = null;
/**
* {@link #setJspId}
*/
private String jspId = null;
/**
* Only consulted in setJspId to detect the iterator case. Set in {@link #release}. Never cleared.
*/
// private String oldJspId = null;
/**
* This is simply the jspId prefixed by {@link #UNIQUE_ID_PREFIX}.
*/
private String facesJspId = null;
/**
*
* The component identifier for the associated component.
*
*/
private String id = null;
/**
* Caches the nearest enclosing {@link 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;
Map> namingContainerChildIds = null;
public UIComponentClassicTagBase() {
}
UIComponentClassicTagBase(PageContext pageContext, FacesContext facesContext) {
this.pageContext = pageContext;
context = 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
*
* @return the value to return from doStart()
*/
protected int getDoStartValue() throws JspException {
int result = EVAL_BODY_BUFFERED;
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
*
* @return the value to return from doEnd()
*/
protected int getDoEndValue() throws JspException {
return EVAL_PAGE;
}
/**
*
* Delegate to the encodeBegin() method of our corresponding {@link 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.
*
* @throws IOException if an input/output error occurs
*
* @deprecated No encoding is done during Jakarta Server Pages page execution. Encoding is deferred until the page has
* completed executing to allow the entire tree to be built before any encoding occurs.
*/
@Deprecated
protected void encodeBegin() throws IOException {
component.encodeBegin(context);
}
/**
*
* Delegate to the encodeChildren() method of our corresponding {@link 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.
*
* @throws IOException if an input/output error occurs
*
* @deprecated No encoding is done during Jakarta Server Pages page execution. Encoding is deferred until the page has
* completed executing to allow the entire tree to be built before any encoding occurs.
*/
@Deprecated
protected void encodeChildren() throws IOException {
component.encodeChildren(context);
}
/**
*
* Delegate to the encodeEnd() method of our corresponding {@link 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.
*
* @throws IOException if an input/output error occurs
*
* @deprecated No encoding is done during Jakarta Server Pages page execution. Encoding is deferred until the page has
* completed executing to allow the entire tree to be built before any encoding occurs.
*/
@Deprecated
protected void encodeEnd() throws IOException {
component.encodeEnd(context);
}
// --------------------------------------------------------- Tag Properties
/**
*
* Set the PageContext of the page containing this tag instance.
*
*
* @param pageContext The enclosing PageContext
*/
@Override
public void setPageContext(PageContext pageContext) {
this.pageContext = pageContext;
}
/**
*
* Return the Tag that is the parent of this instance.
*
*/
@Override
public Tag getParent() {
return parent;
}
/**
*
* Set the Tag that is the parent of this instance.
*
*
* @param parent The new parent Tag
*/
@Override
public void setParent(Tag parent) {
this.parent = parent;
}
//
// Complex methods to support Tag
//
/**
*
* Set up the {@link jakarta.faces.context.ResponseWriter} for the current response, if this has not been done already.
*
*
* @deprecated {@link jakarta.faces.application.ViewHandler#renderView} is now responsible for setting up the response
* writer. This method is now a no-op.
*/
@Deprecated
protected void setupResponseWriter() {
}
/**
*
* Create a new child component using createComponent, initialize its properties, and add it to its parent
* as a child.
*
*
* @param context {@link FacesContext} for the current request
* @param parent Parent {@link UIComponent} for the new child
* @param componentId Component identifier for the new child, or null for no explicit identifier
*/
private UIComponent createChild(FacesContext context, UIComponent parent, UIComponentClassicTagBase parentTag, String componentId) throws JspException {
UIComponent component = createComponent(context, componentId);
int indexOfNextChildTag = parentTag.getIndexOfNextChildTag();
if (indexOfNextChildTag > parent.getChildCount()) {
indexOfNextChildTag = parent.getChildCount();
}
parent.getChildren().add(indexOfNextChildTag, component);
created = true;
return component;
}
/**
*
* Create a new child component using createComponent, initialize its properties, and add it to its parent
* as a facet.
*
*
* @param context {@link FacesContext} for the current request
* @param parent Parent {@link UIComponent} of the new facet
* @param name Name of the new facet
* @param newId id of the new facet
*/
private UIComponent createFacet(FacesContext context, UIComponent parent, String name, String newId) throws JspException {
UIComponent component = createComponent(context, newId);
parent.getFacets().put(name, component);
created = true;
return component;
}
/**
*
* Return a child with the specified component id from the specified component, if any; otherwise, return
* null.
*
*
* @param component {@link UIComponent} to be searched
* @param componentId Component id to search for
*/
private static UIComponent getChild(UIComponentClassicTagBase tag, UIComponent component, String componentId) {
int childCount = component.getChildCount();
// we only need to bother to check if we even have children
if (childCount > 0) {
List children = 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 = startIndex; i < childCount; i++) {
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 < startIndex; i++) {
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 {@link UIComponent}, from the component tree, that corresponds to this tag handler instance. If
* there is no such {@link UIComponent}, create one and add it as a child or facet of the {@link UIComponent} associated
* with our nearest enclosing {@link UIComponentTag}. The process for locating or creating the component is:
*
*
*
If we have previously located this component, return it.
*
Locate the parent component by looking for a parent {@link UIComponentTag} instance, and ask it for its
* component. If there is no parent {@link UIComponentTag} instance, this tag represents the root component, so get it
* from the current Tree and return it.
*
If this {@link UIComponentTag} instance has the facetName attribute set, ask the parent
* {@link 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
* {@link UIComponent}.
*
Determine the component id to be assigned to the new component, as follows: if this {@link UIComponentTag} has an
* id attribute set, use that value; otherwise, generate an identifier that is guaranteed to be the same
* for this {@link UIComponent} every time this page is processed (i.e. one based on the location of all
* {@link UIComponentTag} instances without an id attribute set).
*
Ask the parent {@link 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 {@link UIComponent}.
*
*
* When creating a component, the process is:
*
*
*
Retrieve the component type by calling {@link UIComponentTag#getComponentType}
*
If the component has a binding attribute, create an expression from it, and call
* {@link Application#createComponent} with that expression, the {@link FacesContext}, and the component type. Store the
* expression using the key "binding".
*
Otherwise, call {@link Application#createComponent} with only the component type.
*
Call setProperties().
*
Add the new component as a child or facet of its parent
*
*
* @param context the {@code FacesContext} for the current request.
*
* @return the found component
*
* @throws JspException if an unexpected condition arises while finding the component
*/
protected UIComponent findComponent(FacesContext context) throws JspException {
// Step 1 -- Have we already found the relevant component?
if (component != null) {
return component;
}
// Step 2 -- Identify the component that is, or will be, our parent
UIComponentClassicTagBase parentTag = _getParentUIComponentClassicTagBase(context.getAttributes());
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(CURRENT_VIEW_ROOT)) {
// 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 != id) {
parentComponent.setId(id);
} else {
assert null != getFacesJspId();
parentComponent.setId(getFacesJspId());
}
parentComponent.getAttributes().put(CURRENT_VIEW_ROOT, CURRENT_VIEW_ROOT);
created = 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.
component = parentComponent;
return component;
}
// 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) {
component = parentComponent.getFacets().get(facetName);
if (component == null) {
component = createFacet(context, parentComponent, facetName, newId);
}
return component;
} else {
// Step 5 -- Create or return a child with the specified id
component = getChild(parentTag, parentComponent, newId);
if (component == null) {
component = createChild(context, parentComponent, parentTag, newId);
}
return component;
}
}
//
// Tag tree navigation
//
/**
*
* Locate and return the nearest enclosing {@link UIComponentClassicTagBase} if any; otherwise, return
* null.
*
*
* @param context PageContext for the current page
*
* @return the parent tag
*/
public static UIComponentClassicTagBase getParentUIComponentClassicTagBase(PageContext context) {
return _getParentUIComponentClassicTagBase(getFacesContext(context));
}
private static UIComponentClassicTagBase _getParentUIComponentClassicTagBase(FacesContext facesContext) {
return _getParentUIComponentClassicTagBase(facesContext.getAttributes());
}
private static UIComponentClassicTagBase _getParentUIComponentClassicTagBase(Map