📄 capturestatephaselistener.java
字号:
package com.mycompany.jsf.event;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.beans.Introspector;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import com.mycompany.jsf.model.TreeNode;
/**
* This class is a JSF PhaseListener that captures view state before
* and after each request processing lifecycle phase.
* <p>
* It saves the state as a tree composed of TreeNode instances in
* a session scope Map named "com.mycompany.debug", with an entry
* per view keyed by the view ID.
*
* @author Hans Bergsten, Gefion Software <hans@gefionsoftware.com>
* @version 1.0
*/
public class CaptureStatePhaseListener implements PhaseListener {
private Map pdCache = Collections.synchronizedMap(new HashMap());
/**
* Returns PhaseId.ANY_PHASE to announce that this listener
* must be invoked in all phases.
*/
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
/**
* Saves the view state before the regular processing of the view
* in the current phase by calling capturePhaseData(), unless
* the current phase is Restore View (there's no view available
* in this case).
*/
public void beforePhase(PhaseEvent event) {
String phaseName = event.getPhaseId().toString();
if (event.getPhaseId() != PhaseId.RESTORE_VIEW) {
capturePhaseData("Before " + phaseName, event.getFacesContext());
}
}
/**
* Saves the view state after the regular processing of the view
* in the current phase by calling capturePhaseData(). If the
* current phase is Render Response, also saves general request
* data by calling captureRequestData().
*/
public void afterPhase(PhaseEvent event) {
String phaseName = event.getPhaseId().toString();
capturePhaseData("After " + phaseName, event.getFacesContext());
if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
captureRequestData(event.getFacesContext());
}
}
/**
* Returns the TreeNode for the tree root, from the Map saved
* as a session scope variable named "com.mycompany.debug" or
* a new instance if it's not found or the found instance is
* for a previous request.
*/
private TreeNode getRoot(FacesContext context) {
Map sessionMap = context.getExternalContext().getSessionMap();
Map debugMap = (Map) sessionMap.get("com.mycompany.debug");
if (debugMap == null) {
debugMap = new HashMap();
sessionMap.put("com.mycompany.debug", debugMap);
}
String viewId = getViewId(context);
TreeNode root = (TreeNode) debugMap.get(viewId);
if (root == null || !context.equals(root.getValue())) {
// First request or old data from previous request
root = new TreeNode();
root.setName("root");
root.setValue(context);
root.setExpanded(true);
debugMap.put(viewId, root);
}
return root;
}
/**
* Returns the view ID for the view held by the provided
* FacesContext, adjusted if needed. For the first phases
* on a new view, the viewId may have the wrong extension. Just
* replace it with ".jsp" (should really look at mapping).
*/
private String getViewId(FacesContext context) {
String viewId = context.getViewRoot().getViewId();
int extPos = viewId.lastIndexOf('.');
if (extPos > 0) {
viewId = viewId.substring(0, extPos) + ".jsp";
}
return viewId;
}
/**
* Creates nodes for the request data. Nodes for request headers,
* request parameters, and request locales are created and added
* as a branch under the root of the tree.
*/
private void captureRequestData(FacesContext context) {
TreeNode root = getRoot(context);
TreeNode requestNode = new TreeNode();
requestNode.setName("ExternalContext");
root.addChild(requestNode);
TreeNode headersNode = new TreeNode();
headersNode.setName("requestHeaderMap");
Map headersMap = context.getExternalContext().getRequestHeaderMap();
addLeafNodes(headersNode, headersMap);
requestNode.addChild(headersNode);
TreeNode paramsNode = new TreeNode();
paramsNode.setName("requestParameterValuesMap");
Map paramsMap =
context.getExternalContext().getRequestParameterValuesMap();
addLeafNodes(paramsNode, paramsMap);
requestNode.addChild(paramsNode);
TreeNode localesNode = new TreeNode();
localesNode.setLeafNode(true);
localesNode.setName("requestLocales");
Iterator locales = context.getExternalContext().getRequestLocales();
localesNode.setValue(format(locales));
requestNode.addChild(localesNode);
}
/**
* Creates nodes for the view. Nodes for each component in the
* view's component tree and all scoped variables are created and
* added as a branch under the root of the tree.
*/
private void capturePhaseData(String phaseName, FacesContext context) {
TreeNode root = getRoot(context);
TreeNode phaseNode = new TreeNode();
phaseNode.setName(phaseName);
root.addChild(phaseNode);
TreeNode compNode = new TreeNode();
UIComponent viewRoot = context.getViewRoot();
compNode.setName("viewRoot [" + viewRoot.getClass().getName() + "]");
addComponentNodes(context, compNode, viewRoot);
phaseNode.addChild(compNode);
TreeNode varNode = new TreeNode();
varNode.setName("Scoped Variables");
phaseNode.addChild(varNode);
TreeNode appNode = new TreeNode();
appNode.setName("applicationMap");
Map appMap = context.getExternalContext().getApplicationMap();
addLeafNodes(appNode, appMap);
varNode.addChild(appNode);
TreeNode sessionNode = new TreeNode();
sessionNode.setName("sessionMap");
Map sessionMap = context.getExternalContext().getSessionMap();
addLeafNodes(sessionNode, sessionMap);
varNode.addChild(sessionNode);
TreeNode requestNode = new TreeNode();
requestNode.setName("requestMap");
Map requestMap = context.getExternalContext().getRequestMap();
addLeafNodes(requestNode, requestMap);
varNode.addChild(requestNode);
}
/**
* Creates nodes for properties and attributes of the provided
* component and adds them as branches under the provided node,
* and then recursively calls itself for each child and facet
* of the provided component.
*/
private void addComponentNodes(FacesContext context, TreeNode parent,
UIComponent comp) {
TreeNode propsNode = new TreeNode();
propsNode.setName("Properties");
PropertyDescriptor[] pds =
(PropertyDescriptor[]) pdCache.get(comp.getClass());
if (pds == null) {
try {
BeanInfo bi =
Introspector.getBeanInfo(comp.getClass(), Object.class);
pds = bi.getPropertyDescriptors();
pdCache.put(comp.getClass(), pds);
}
catch (Exception e) {};
}
if (pds != null) {
for (int i = 0; pds != null && i < pds.length; i++) {
String name = pds[i].getName();
if ("attributes".equals(name) ||
"children".equals(name) ||
"facets".equals(name) ||
"facetsAndChildren".equals(name) ||
"parent".equals(name)) {
continue;
}
TreeNode propNode = new TreeNode();
propNode.setLeafNode(true);
propNode.setName(name);
Object value = null;
Method m = pds[i].getReadMethod();
if (m == null) {
value = "--- No read method ---";
}
else {
try {
value = m.invoke(comp, null);
}
catch (Exception e) {}
}
propNode.setValue(toString(value));
propsNode.addChild(propNode);
}
parent.addChild(propsNode);
}
TreeNode attrsNode = new TreeNode();
attrsNode.setName("Attributes");
Iterator attrs = comp.getAttributes().entrySet().iterator();
while (attrs.hasNext()) {
Map.Entry me = (Map.Entry) attrs.next();
TreeNode attrNode = new TreeNode();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -