/* | |
* 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 org.apache.empire.jsf2.pages; | |
import java.util.Map; | |
import javax.faces.component.UIViewRoot; | |
import javax.faces.context.FacesContext; | |
import javax.faces.event.PhaseEvent; | |
import javax.faces.event.PhaseId; | |
import javax.faces.event.PhaseListener; | |
import org.apache.commons.beanutils.BeanUtils; | |
import org.apache.empire.exceptions.InternalException; | |
import org.apache.empire.exceptions.ObjectNotValidException; | |
import org.apache.empire.jsf2.app.FacesUtils; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
public class PagePhaseListener implements PhaseListener | |
{ | |
private static final long serialVersionUID = 1L; | |
private static final Logger log = LoggerFactory.getLogger(PagePhaseListener.class); | |
private static final String LAST_PAGE_VIEW_ID = "lastPageViewId"; | |
// FORWARD_PAGE_PARAMS used by PageNavigationHandler | |
public static final String FORWARD_PAGE_PARAMS = "forwardPageParams"; | |
public PagePhaseListener() | |
{ | |
log.trace("PagePhaseListener created."); | |
} | |
@Override | |
public PhaseId getPhaseId() | |
{ | |
return PhaseId.ANY_PHASE; | |
} | |
@Override | |
public void beforePhase(PhaseEvent pe) | |
{ | |
PhaseId phaseId = pe.getPhaseId(); | |
if (log.isTraceEnabled()) | |
log.trace("Processing Phase {}.", phaseId); | |
FacesContext fc = pe.getFacesContext(); | |
UIViewRoot vr = fc.getViewRoot(); | |
if (vr == null) | |
{ | |
/* | |
PartialViewContext pvc = fc.getPartialViewContext(); | |
boolean ajax = pvc.isAjaxRequest(); | |
boolean part = pvc.isPartialRequest(); | |
if (!part && !ajax) | |
{ | |
HttpServletRequest req = FacesUtils.getHttpRequest(fc); | |
String reqURI = req.getRequestURI(); | |
log.info("No View Root for request to '"+reqURI+"' in Phase "+String.valueOf(phaseId)); | |
} | |
*/ | |
return; | |
} | |
// Get the view Id | |
String viewId = vr.getViewId(); | |
if (viewId==null) | |
{ // Error: No viewId! | |
log.warn("No viewId provided for PagePhaseEvent in phase {}.", phaseId); | |
return; | |
} | |
// Detect view change | |
Map<String, Object> sessionMap = fc.getExternalContext().getSessionMap(); | |
Object lastViewId = sessionMap.get(LAST_PAGE_VIEW_ID); | |
if (lastViewId == null || !(((String) lastViewId).equalsIgnoreCase(viewId))) | |
{ // view changes | |
FacesUtils.getWebApplication().onChangeView(fc, viewId); | |
if (fc.getResponseComplete()) | |
return; | |
// set view Id | |
sessionMap.put(LAST_PAGE_VIEW_ID, viewId); | |
} | |
// Get Page Definition | |
PageDefinition pageDef = PageDefinitions.getInstance().getPageFromViewId(viewId); | |
if (pageDef == null) | |
{ // No page definition available | |
if (log.isDebugEnabled()) | |
log.debug("No page definition available for viewId {}.", viewId); | |
return; | |
} | |
// Check Request context path | |
/* | |
if (viewChanged) | |
{ | |
log.debug("Checking view context path"); | |
HttpServletRequest req = FacesUtils.getHttpRequest(fc); | |
String reqURI = req.getRequestURI(); | |
viewId = pageDef.getPath(); | |
int vix = viewId.lastIndexOf('.'); | |
int rix = reqURI.lastIndexOf('.'); | |
if (rix<vix || !viewId.regionMatches(true, 0, reqURI, rix-vix, vix)) | |
{ // redirect to view page | |
String ctxPath = fc.getExternalContext().getRequestContextPath(); | |
String pageURI = ctxPath + viewId.substring(0,vix) + ".iface"; | |
log.warn("Invalid RequestURI '" + reqURI + "'. Redirecting to '"+pageURI+"'."); | |
FacesUtils.redirectDirectly(fc, pageURI); | |
return; | |
} | |
// Save current viewId | |
} | |
*/ | |
// Obtain PageBean from BeanManager | |
String name = pageDef.getPageBeanName(); | |
Map<String, Object> viewMap = vr.getViewMap(); | |
Page pageBean = (Page) viewMap.get(name); | |
if (pageBean == null) | |
{ // Not available yet | |
Class<? extends Page> pageClass = pageDef.getPageBeanClass(); | |
if (log.isDebugEnabled()) | |
log.debug("Creating page bean {} for {} in Phase {}.", new Object[] { pageClass.getName(), viewId, pe.getPhaseId() }); | |
// Use Bean Manager | |
pageBean = (Page)FacesUtils.getManagedBean(fc, name); | |
if (pageBean==null) | |
{ // Create Instance ourselves | |
log.warn("Unable to obtain page bean '{}' from BeanManager. Page bean probably not registered. Creating new instance but Injection might not work! ", name); | |
try | |
{ // Create Instance | |
pageBean = pageClass.newInstance(); | |
viewMap.put(name, pageBean); | |
} | |
catch (Exception e) | |
{ | |
log.error("Error creating instance of page bean " + pageClass.getName(), e); | |
throw new InternalException(e); | |
} | |
} | |
else if (!pageClass.isInstance(pageBean)) | |
{ // Wrong class | |
log.warn("Page bean '"+name+"' is not an instance of class {} as expected. Detected class is {}", pageClass.getName(), pageBean.getClass().getName()); | |
} | |
// Add 'page' to map | |
viewMap.put("page", pageBean); | |
} | |
// set definition | |
pageBean.setPageDefinition(pageDef); | |
// Init PageBean | |
if (pe.getPhaseId() == PhaseId.RENDER_RESPONSE) | |
initPageBean(pageBean, fc, viewMap); | |
/* | |
Collection<UIViewParameter> params = ViewMetadata.getViewParameters(vr); | |
for (UIViewParameter p : params) | |
{ | |
log.info("p {} = {}", p.getName(), p.getValue()); | |
} | |
*/ | |
} | |
private void initPageBean(Page pageBean, FacesContext fc, Map<String, Object> viewMap) | |
{ | |
if (!pageBean.isInitialized()) | |
{ // Not yet initialized | |
if (!PageNavigationHandler.isInitialized()) | |
{ // Probably missing declaration in faces-config.xml | |
log.error("PageNavigationHandler has not been initialized. Forward operations will not work!"); | |
} | |
// Check for forward page params | |
if (viewMap.containsKey(FORWARD_PAGE_PARAMS)) | |
{ | |
@SuppressWarnings("unchecked") | |
Map<String, String> pageParams = (Map<String, String>) viewMap.remove(FORWARD_PAGE_PARAMS); | |
// TODO: Set view metadata | |
if (!setViewMetadata(pageParams)) | |
{ // instead set properties directly | |
for (String name : pageParams.keySet()) | |
{ | |
String value = pageParams.get(name); | |
try | |
{ | |
BeanUtils.setProperty(pageBean, name, value); | |
} | |
catch (Exception e) | |
{ | |
log.error("Unable to set PageParam " + name + " on " + pageBean.getClass().getName() + ".", e); | |
} | |
} | |
} | |
} | |
// page prepared | |
} | |
// Init now | |
pageBean.preRenderPage(fc); | |
} | |
/** | |
* TODO: Find a way to set the view Metadata. Don't know how to do it. | |
* | |
* @param pageParams | |
* @return | |
*/ | |
private boolean setViewMetadata(Map<String, String> pageParams) | |
{ | |
// Getting the metadata facet of the view | |
/* | |
FacesContext fc = FacesContext.getCurrentInstance(); | |
UIViewRoot vr = fc.getViewRoot(); | |
UIComponent metadataFacet = vr.getFacet(UIViewRoot.METADATA_FACET_NAME); | |
*/ | |
/* | |
String viewId = vr.getViewId(); | |
ViewDeclarationLanguage vdl = fc.getApplication().getViewHandler().getViewDeclarationLanguage(fc, viewId); | |
ViewMetadata viewMetadata = vdl.getViewMetadata(fc, viewId); | |
Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(vr); | |
for (UIComponent child : metadataFacet.getChildren()) | |
*/ | |
/* | |
UIComponent metadata = vr.getFacet(UIViewRoot.METADATA_FACET_NAME); | |
if (metadata == null) | |
{ | |
metadata = fc.getApplication().createComponent(UIPanel.COMPONENT_TYPE); | |
vr.getFacets().put(UIViewRoot.METADATA_FACET_NAME, metadata); | |
Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(vr); | |
int size = viewParams.size(); | |
for (String name : pageParams.keySet()) | |
{ | |
String value = pageParams.get(name); | |
UIViewParameter uivp = new UIViewParameter(); | |
uivp.setName(name); | |
uivp.setValue(value); | |
// uivp.setParent(vr); | |
metadata.getChildren().add(uivp); | |
} | |
} | |
for (UIComponent child : metadata.getChildren()) | |
{ | |
if (child instanceof UIViewParameter) | |
{ | |
UIViewParameter viewParam = (UIViewParameter) child; | |
String value = pageParams.get(viewParam.getName()); | |
if (value != null) | |
viewParam.setValue(value); | |
} | |
} | |
*/ | |
return false; | |
} | |
@Override | |
public void afterPhase(PhaseEvent pe) | |
{ | |
if (pe.getPhaseId() != PhaseId.RENDER_RESPONSE) | |
return; | |
// Get the view | |
UIViewRoot vr = pe.getFacesContext().getViewRoot(); | |
if (vr==null) | |
return; | |
// Check Page Bean | |
Map<String, Object> viewMap = vr.getViewMap(); | |
Page pageBean = (Page) viewMap.get("page"); | |
if (pageBean != null && !pageBean.isInitialized()) | |
{ | |
log.warn("PageBean was not initialized!"); | |
throw new ObjectNotValidException(pageBean); | |
} | |
// FacesUtils.getFin2Application().releaseConnection(true); | |
log.trace("PagePhase complete."); | |
} | |
} |