FileDocCategorySizeDatePackage
CaptureStatePhaseListener.javaAPI DocExample15844Tue Jun 08 11:26:42 BST 2004com.mycompany.jsf.event

CaptureStatePhaseListener

public class CaptureStatePhaseListener extends Object implements javax.faces.event.PhaseListener
This class is a JSF PhaseListener that captures view state before and after each request processing lifecycle phase.

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
version
1.0

Fields Summary
private Map
pdCache
Constructors Summary
Methods Summary
private voidaddComponentNodes(javax.faces.context.FacesContext context, com.mycompany.jsf.model.TreeNode parent, javax.faces.component.UIComponent comp)
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.


	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();
	    attrNode.setLeafNode(true);
	    attrNode.setName(me.getKey().toString());
	    attrNode.setValue(toString(me.getValue()));
	    attrsNode.addChild(attrNode);
	}
	parent.addChild(attrsNode);

	if (comp.getChildCount() > 0) {
	    TreeNode kidsNode = new TreeNode();
	    kidsNode.setName("Children");
	    Iterator kids = comp.getChildren().iterator();
	    while (kids.hasNext()) {
		UIComponent child = (UIComponent) kids.next();
		TreeNode childNode = new TreeNode();
		childNode.setName(child.getClientId(context) +
			 " [" + child.getClass().getName() + "]");
		kidsNode.addChild(childNode);
		addComponentNodes(context, childNode, child);
	    }
	    parent.addChild(kidsNode);
	}

	Map facetsMap = comp.getFacets();
	if (facetsMap.size() > 0) {
	    TreeNode facetsNode = new TreeNode();
	    facetsNode.setName("Facets");
	    Iterator facets = facetsMap.entrySet().iterator();
	    while (facets.hasNext()) {
		Map.Entry me = (Map.Entry) facets.next();
		UIComponent child = (UIComponent) me.getValue();
		TreeNode childNode = new TreeNode();
		childNode.setName((String) me.getKey());
		facetsNode.addChild(childNode);
		addComponentNodes(context, childNode, child);
	    }
	    parent.addChild(facetsNode);
	}
    
private voidaddLeafNodes(com.mycompany.jsf.model.TreeNode parent, java.util.Map map)
Add a TreeNode instance for each entry in the Map, with the entry key (converted to a String) as the node name, the entry value (converted to a String) as the node value, and with the "leafNode" property set to "true".

	Iterator i = map.entrySet().iterator();
	while (i.hasNext()) {
	    Map.Entry me = (Map.Entry) i.next();
	    TreeNode leaf = new TreeNode();
	    leaf.setLeafNode(true);
	    leaf.setName(me.getKey().toString());
	    leaf.setValue(toString(me.getValue()));
	    parent.addChild(leaf);
	}
    
public voidafterPhase(javax.faces.event.PhaseEvent event)
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().

	String phaseName = event.getPhaseId().toString();
	capturePhaseData("After " + phaseName, event.getFacesContext());

	if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
	    captureRequestData(event.getFacesContext());
	}
    
public voidbeforePhase(javax.faces.event.PhaseEvent event)
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).

	String phaseName = event.getPhaseId().toString();
	if (event.getPhaseId() != PhaseId.RESTORE_VIEW) {
	    capturePhaseData("Before " + phaseName, event.getFacesContext());
	}
    
private voidcapturePhaseData(java.lang.String phaseName, javax.faces.context.FacesContext context)
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.

	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);
    
private voidcaptureRequestData(javax.faces.context.FacesContext context)
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.

	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);
    
private java.lang.Stringformat(java.util.Iterator i)
Returns a String with comma-separated list of the values represented by the Iterator.

	StringBuffer sb = new StringBuffer();
	boolean first = true;
	while (i.hasNext()) {
	    Object o = i.next();
	    if (!first) {
		sb.append(", ");
	    }
	    first = false;
	    sb.append(o);
	}
	return sb.toString();
    
private java.lang.Stringformat(java.util.Map map)
Returns a String with comma-separated list of the Map entries, with each entry as "key = value".

	Iterator i = map.entrySet().iterator();
	StringBuffer sb = new StringBuffer();
	boolean first = true;
	while (i.hasNext()) {
	    Map.Entry me = (Map.Entry) i.next();
	    if (!first) {
		sb.append(", ");
	    }
	    first = false;
	    sb.append(me.getKey()).append("=").append(me.getValue());
	}
	return sb.toString();
    
public javax.faces.event.PhaseIdgetPhaseId()
Returns PhaseId.ANY_PHASE to announce that this listener must be invoked in all phases.


                      
       
	return PhaseId.ANY_PHASE;
    
private com.mycompany.jsf.model.TreeNodegetRoot(javax.faces.context.FacesContext context)
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.

	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;
    
private java.lang.StringgetViewId(javax.faces.context.FacesContext context)
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).

	String viewId = context.getViewRoot().getViewId();
	int extPos = viewId.lastIndexOf('.");
	if (extPos > 0) {
	    viewId = viewId.substring(0, extPos) + ".jsp";
	}
	return viewId;
    
private java.lang.Object[]toObjects(boolean[] arr)
Returns an Object array with the values of the array.

	Object[] objects = new Object[Array.getLength(arr)];
	for (int i = 0; i < arr.length; i++) {
	    objects[i] = Array.get(arr, i);
	}
	return objects;		     
    
private java.lang.Object[]toObjects(byte[] arr)
Returns an Object array with the values of the array.

	Object[] objects = new Object[Array.getLength(arr)];
	for (int i = 0; i < arr.length; i++) {
	    objects[i] = Array.get(arr, i);
	}
	return objects;		     
    
private java.lang.Object[]toObjects(char[] arr)
Returns an Object array with the values of the array.

	Object[] objects = new Object[Array.getLength(arr)];
	for (int i = 0; i < arr.length; i++) {
	    objects[i] = Array.get(arr, i);
	}
	return objects;		     
    
private java.lang.Object[]toObjects(double[] arr)
Returns an Object array with the values of the array.

	Object[] objects = new Object[Array.getLength(arr)];
	for (int i = 0; i < arr.length; i++) {
	    objects[i] = Array.get(arr, i);
	}
	return objects;		     
    
private java.lang.Object[]toObjects(float[] arr)
Returns an Object array with the values of the array.

	Object[] objects = new Object[Array.getLength(arr)];
	for (int i = 0; i < arr.length; i++) {
	    objects[i] = Array.get(arr, i);
	}
	return objects;		     
    
private java.lang.Object[]toObjects(int[] arr)
Returns an Object array with the values of the array.

	Object[] objects = new Object[Array.getLength(arr)];
	for (int i = 0; i < arr.length; i++) {
	    objects[i] = Array.get(arr, i);
	}
	return objects;		     
    
private java.lang.Object[]toObjects(short[] arr)
Returns an Object array with the values of the array.

	Object[] objects = new Object[Array.getLength(arr)];
	for (int i = 0; i < arr.length; i++) {
	    objects[i] = Array.get(arr, i);
	}
	return objects;		     
    
private java.lang.Object[]toObjects(long[] arr)
Returns an Object array with the values of the array.

	Object[] objects = new Object[Array.getLength(arr)];
	for (int i = 0; i < arr.length; i++) {
	    objects[i] = Array.get(arr, i);
	}
	return objects;		     
    
private java.lang.StringtoString(java.lang.Object value)
Returns the value as a String in an appropriate format depending on the data type. A null value is returned as "null", an Object or primitive type array or a Collection is returned as a comma-separated list of values, a Map is returned as a comma-separated list of "key=value" entries.

	if (value == null) {
	    return "null";
	}
	
	String string = null;

	// Use element values for common mutable types
	if (value.getClass().isArray()) {
	    if (value.getClass().getComponentType().isPrimitive()) {
		if (value.getClass().getComponentType() == Boolean.TYPE) {
		    Object[] arr = toObjects((boolean[]) value);
		    string = format(Arrays.asList(arr).iterator());
		}
		if (value.getClass().getComponentType() == Byte.TYPE) {
		    Object[] arr = toObjects((byte[]) value);
		    string = format(Arrays.asList(arr).iterator());
		}
		if (value.getClass().getComponentType() == Character.TYPE) {
		    Object[] arr = toObjects((char[]) value);
		    string = format(Arrays.asList(arr).iterator());
		}
		if (value.getClass().getComponentType() == Double.TYPE) {
		    Object[] arr = toObjects((double[]) value);
		    string = format(Arrays.asList(arr).iterator());
		}
		if (value.getClass().getComponentType() == Float.TYPE) {
		    Object[] arr = toObjects((float[]) value);
		    string = format(Arrays.asList(arr).iterator());
		}
		if (value.getClass().getComponentType() == Integer.TYPE) {
		    Object[] arr = toObjects((int[]) value);
		    string = format(Arrays.asList(arr).iterator());
		}
		if (value.getClass().getComponentType() == Long.TYPE) {
		    Object[] arr = toObjects((long[]) value);
		    string = format(Arrays.asList(arr).iterator());
		}
		if (value.getClass().getComponentType() == Short.TYPE) {
		    Object[] arr = toObjects((short[]) value);
		    string = format(Arrays.asList(arr).iterator());
		}
	    }
	    else {
		string = format(Arrays.asList((Object[]) value).iterator());
	    }
	}
	else if (value instanceof Collection) {
	    string = format(((Collection) value).iterator());
	}
	else if (value instanceof Map) {
	    string = format((Map) value);		
	}
	else {
	    string = value.toString();
	}
	return string;