// Determine whether or not the resource is already present in the <head> section of the portal page.
// Note that this can happen in one of two ways: 1) If this is NON-Liferay-Runtime portlet (currently
// doing Ajax) but has already added the resource during initial page HTTP-GET render, or 2) By another
// NON-Liferay-Runtime portlet that has already added the same JavaScript resource.
ComponentResource componentResource = componentResourceFactory.getComponentResource(
uiComponentResource);
boolean alreadyPresentInPortalPageHead = headResourceIdsFromManagedBean.contains(
componentResource.getId());
// If the resource is already present in the <head> section of the portal page, then simply output a
// logger message to this fact.
if (alreadyPresentInPortalPageHead) {
if (logger.isDebugEnabled()) {
logger.debug(
"Resource already present in head: name=[{0}] library=[{1}] rendererType=[{2}] value=[{3}] className=[{4}]",
new Object[] {
componentResource.getName(), componentResource.getLibrary(),
uiComponentResource.getRendererType(),
ComponentResourceUtil.getComponentValue(uiComponentResource),
uiComponentResource.getClass().getName(),
});
}
}
// Otherwise, since it is not possible to add it to the <head> section, the resource must be relocated
// to the body.
else {
logger.debug(
"Relocating resource to body (since it was added via Ajax and is not yet present in head): name=[{0}] library=[{1}] rendererType=[{2}] value=[{3}] className=[{4}]",
new Object[] {
componentResource.getName(), componentResource.getLibrary(),
uiComponentResource.getRendererType(),
ComponentResourceUtil.getComponentValue(uiComponentResource),
uiComponentResource.getClass().getName(),
});
resourcesForRelocatingToBody.add(uiComponentResource);
}
}
// Otherwise, if the portlet container has the ability to add resources to the <head> section of the
// portal page, then add it to the list of resources that are to be added to the <head> section.
else if (portletContainerAbleToAddScriptResourceToHead) {
resourcesForAddingToHead.add(uiComponentResource);
}
// Otherwise, we have no choice but to add it to the list of resources that are to be relocated to
// the body.
else {
resourcesForRelocatingToBody.add(uiComponentResource);
}
}
// If the portlet container has the ability to add resources to the <head> section of the portal page, then
if (portletContainerAbleToAddScriptResourceToHead) {
// Save a temporary reference to the ResponseWriter provided by the FacesContext.
ResponseWriter responseWriterBackup = facesContext.getResponseWriter();
// Replace the ResponseWriter in the FacesContext with a HeadResponseWriter that knows how to write to
// the <head>...</head> section of the rendered portal page.
HeadResponseWriter headResponseWriter = (HeadResponseWriter) portletRequest.getAttribute(
HeadResponseWriter.class.getName());
if (headResponseWriter == null) {
headResponseWriter = (HeadResponseWriter) portletContainer.getHeadResponseWriter(responseWriterBackup);
}
portletRequest.setAttribute(HeadResponseWriter.class.getName(), headResponseWriter);
facesContext.setResponseWriter(headResponseWriter);
// For each resource:
for (UIComponent uiComponentResource : resourcesForAddingToHead) {
ComponentResource componentResource = componentResourceFactory.getComponentResource(
uiComponentResource);
// Command the resource to render itself to the HeadResponseWriter
if (componentResource.isRenderable()) {
uiComponentResource.encodeAll(facesContext);
}
String resourceId = componentResource.getId();
// If the resource has not yet been marked as having been added, then mark it now. Note that unless the
// resource is a RichFaces Resource Library (see comments below), the resource has probably already been
// marked as being in the head by ResourceRendererBridgeImpl#encodeEnd(FacesContext, UIComponent).
if (!headResourceIdsFromManagedBean.contains(resourceId)) {
headResourceIdsFromManagedBean.add(resourceId);
if (logger.isDebugEnabled()) {
if (resourceId.endsWith(RICHFACES_RESLIB_SUFFIX) ||
RENDERER_TYPE_RICHFACES_RESOURCE_LIBRARY.equals(
uiComponentResource.getRendererType())) {
// RichFaces has resources like "org.richfaces:base-component.reslib",
// "org.richfaces:message.reslib", and "org.richfaces:ajax.reslib" that represent a
// collection of resources.
logger.debug("Marking RichFaces resource library [{0}] as being present in the head",
resourceId);
}
else {
logger.debug("Marking non-RichFaces resourceId=[{0}] as being present in the head",
resourceId);
}
}
}
}
// Restore the temporary ResponseWriter reference.
facesContext.setResponseWriter(responseWriterBackup);
}
// Relocate resources to the body if necessary. Note that the "ADDED" attribute has to be set to true
// in order to prevent events from firing during the relocation process.
for (UIComponent uiComponentResource : resourcesForRelocatingToBody) {
uiComponentResource.getAttributes().put(ORIGINAL_TARGET, StringPool.HEAD);
uiComponentResource.getAttributes().put(ADDED, Boolean.TRUE);
uiViewRoot.addComponentResource(facesContext, uiComponentResource, StringPool.BODY);
if (logger.isDebugEnabled()) {
ComponentResource componentResource = componentResourceFactory.getComponentResource(
uiComponentResource);
logger.debug(
"Relocating resource to body: name=[{0}] library=[{1}] rendererType=[{2}] value=[{3}] className=[{4}]",
new Object[] {
componentResource.getName(), componentResource.getLibrary(),
uiComponentResource.getRendererType(),
ComponentResourceUtil.getComponentValue(uiComponentResource),
uiComponentResource.getClass().getName(),
});
}