in api/src/main/java/jakarta/faces/component/UIViewRoot.java [199:373]
public void addComponentResource(FacesContext context, UIComponent componentResource, String target)
{
// If the target argument is null
if (target == null)
{
// Look for a target attribute on the component
target = (String)componentResource.getAttributes().get("target");
// If there is no target attribute, set target to be the default value head
if (target == null)
{
target = "head";
}
}
// Call getComponentResources to obtain the child list for the given target
List<UIComponent> componentResources = _getComponentResources(context, target);
// If the component ID of componentResource matches the ID of a resource
// that has already been added, remove the old resource.
String componentId = componentResource.getId();
if (componentId == null)
{
// componentResource can have no id - calling createUniqueId makes us sure that component will have one
// https://issues.apache.org/jira/browse/MYFACES-2775
componentId = createUniqueId(context, null);
componentResource.setId(componentId);
List<UIComponent> children = componentResource.getChildren();
/*
* MYFACES-4631
* Duplicate ID Exception can occur if children also aren't assigned unique IDs
* See https://github.com/primefaces-extensions/primefaces-extensions/issues/517
*/
for(UIComponent child : children) {
String childId = createUniqueId(context, null);
child.setId(childId);
// TODO - Should we nest down further?
}
}
// This var helps to handle the case when we try to add a component that already is
// on the resource list, because PostAddToViewEvent also is sent to components
// backing resources. The problem start when a component is already inside
// componentResources list and we try to relocate it again. This leads to a StackOverflowException
// so we need to check if a component is and prevent remove and add it again. Note
// that remove and then add a component trigger another PostAddToViewEvent. The right
// point to prevent this StackOverflowException is here, because this method is
// responsible to traverse the componentResources list and add when necessary.
boolean alreadyAdded = false;
//The check is only necessary if the component resource is part of the tree.
if (componentResource.isInView())
{
if (componentResource.getParent() != null &&
componentResource.getParent().getId() != null &&
componentResource.getParent().getId().equals(JAKARTA_FACES_LOCATION_PREFIX + target))
{
// We can assume safely that the component is in place, because there is no way to
// put a component resource on a component resource container without call addComponentResource
// so relocation here will not happen.
alreadyAdded = true;
}
else if (componentId != null)
{
for(Iterator<UIComponent> it = componentResources.iterator(); it.hasNext();)
{
UIComponent component = it.next();
if(componentId.equals(component.getId()) && componentResource != component)
{
if (!component.isCachedFacesContext())
{
try
{
component.setCachedFacesContext(context);
it.remove();
}
finally
{
component.setCachedFacesContext(null);
}
}
else
{
it.remove();
}
}
else if (componentResource == component)
{
alreadyAdded = true;
}
}
}
}
else if (componentId != null)
{
for(Iterator<UIComponent> it = componentResources.iterator(); it.hasNext();)
{
UIComponent component = it.next();
if(componentId.equals(component.getId()) && componentResource != component)
{
if (!component.isCachedFacesContext())
{
try
{
component.setCachedFacesContext(context);
it.remove();
}
finally
{
component.setCachedFacesContext(null);
}
}
else
{
it.remove();
}
}
else if (componentResource == component)
{
alreadyAdded = true;
}
}
}
// Add the component resource to the list
if (!alreadyAdded)
{
if (!componentResource.isCachedFacesContext())
{
try
{
componentResource.setCachedFacesContext(context);
componentResources.add(componentResource);
}
finally
{
componentResource.setCachedFacesContext(context);
}
}
else
{
componentResources.add(componentResource);
}
// this is required to make dynamic resource loading possible since Faces 2.3
if (context.getPartialViewContext().isAjaxRequest())
{
boolean isBuildingInitialState
= context.getAttributes().containsKey(StateManager.IS_BUILDING_INITIAL_STATE);
// FaceletViewDeclarationLanguage.isRefreshingTransientBuild(context)
boolean isRefreshTransientBuild
= context.getAttributes().containsKey("org.apache.myfaces.REFRESHING_TRANSIENT_BUILD");
boolean isPostAddToViewEventAfterBuildInitialState =
!isBuildingInitialState || (isBuildingInitialState && isRefreshTransientBuild);
if (isPostAddToViewEventAfterBuildInitialState)
{
try
{
// RequestViewContext requestViewContext = RequestViewContext.getInstance(context);
// requestViewContext.setRenderTarget("head", true, componentResource);
Object requestViewContext = REQUEST_VIEW_CONTEXT_GET_INSTANCE.invoke(null, context);
REQUEST_VIEW_CONTEXT_SET_RENDER_TARGET.invoke(requestViewContext, "head", true, componentResource);
}
catch (Exception e)
{
_getLogger().log(Level.SEVERE, "Could not access RequestViewContext", e);
}
}
}
}
}