Java tutorial
/** * License Agreement. * * Rich Faces - Natural Ajax for Java Server Faces (JSF) * * Copyright (C) 2007 Exadel, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package org.ajax4jsf.application; import java.beans.PropertyDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.faces.FacesException; import javax.faces.component.UIComponent; import javax.faces.component.UIViewRoot; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.faces.el.MethodBinding; import javax.faces.el.ValueBinding; import javax.faces.event.PhaseId; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.ajax4jsf.Messages; import org.ajax4jsf.resource.InternetResource; import org.ajax4jsf.resource.InternetResourceBuilder; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.PropertyUtils; /** * @author asmirnov@exadel.com (latest modification by $Author: alexsmirnov $) * @version $Revision: 1.1.2.1 $ $Date: 2007/01/09 18:57:11 $ * */ public class DebugOutputMaker { private final static String LT = "<"; private final static String GT = ">"; // Attributes that should not be printed static public final HashSet IGNORE_ATTRIBUTES; static { IGNORE_ATTRIBUTES = new HashSet(); IGNORE_ATTRIBUTES.add("attributes"); IGNORE_ATTRIBUTES.add("children"); IGNORE_ATTRIBUTES.add("childCount"); IGNORE_ATTRIBUTES.add("class"); IGNORE_ATTRIBUTES.add("facets"); IGNORE_ATTRIBUTES.add("facetsAndChildren"); IGNORE_ATTRIBUTES.add("parent"); IGNORE_ATTRIBUTES.add("actionListeners"); IGNORE_ATTRIBUTES.add("valueChangeListeners"); IGNORE_ATTRIBUTES.add("validators"); IGNORE_ATTRIBUTES.add("rowData"); IGNORE_ATTRIBUTES.add("javax.faces.webapp.COMPONENT_IDS"); IGNORE_ATTRIBUTES.add("javax.faces.webapp.FACET_NAMES"); IGNORE_ATTRIBUTES.add("javax.faces.webapp.CURRENT_VIEW_ROOT"); } private static final String LOGFILE_PARAM = "org.ajax4jsf.LOGFILE"; /** * Output error state for lifecycle. * * @param context * @param phase * TODO * @param error * @throws IOException */ public void writeErrorMessage(FacesContext context, Throwable e, String phase) throws FacesException { if (null == context) { throw new FacesException(Messages.getMessage(Messages.FACES_CONTEXT_NOT_CREATED), e); } ExternalContext externalContext = context.getExternalContext(); if (null == externalContext) { throw new FacesException(Messages.getMessage(Messages.FACES_CONTEXT_HAS_NOT_EXTERNAL), e); } // debug for http servlet environment, portlets needs other debugger HttpServletResponse response; HttpServletRequest request; try { response = (HttpServletResponse) externalContext.getResponse(); request = (HttpServletRequest) externalContext.getRequest(); response.setContentType("text/html;charset=UTF-8"); // set internal server error status response.setStatus(500); } catch (Exception er) { throw new FacesException(Messages.getMessage(Messages.FACES_CONTEXT_HAS_NOT_RESPONSE), e); } PrintWriter out; try { out = response.getWriter(); } catch (IOException e1) { throw new FacesException(e1.getMessage(), e); } UIViewRoot viewRoot = context.getViewRoot(); String viewId; if (null != viewRoot) { viewId = viewRoot.getViewId(); } else { viewId = request.getRequestURL().toString(); } // output html prolog out.println("<html><head><title>" + Messages.getMessage(Messages.ERROR_ON_PAGE, viewId) + "</title></head><body>"); // write script writeScriptAndStyle(out); // Header PhaseId facesPhase = (PhaseId) context.getExternalContext().getRequestMap() .get(DebugLifecycle.PHASE_ID_PARAM); String errorMessage = (facesPhase == null) ? Messages.getMessage(Messages.LIFECYCLE_ERROR, viewId, phase) : Messages.getMessage(Messages.LIFECYCLE_ERROR_AT_PHASE, new Object[] { viewId, phase, facesPhase.toString() }); out.println("<h1 >"); out.println(errorMessage); out.println("</h1>"); response.setHeader("Ajax-Error-Message", errorMessage + ",\n caused by " + e.getClass().getName() + ", with message: " + e.getMessage()); // Output exceptions writeExceptionStack(e, out); // Output view tree : if (null != viewRoot) { writeComponentsTree(context, out); } else { out.print("<h2 class=' a4j_debug'> " + Messages.getMessage(Messages.COMPONENT_TREE_NOT_CREATED) + " </h2>"); } // Out scope variables writeContextVariables(context, out); // Write log output iframe : writeLog(context, out); // out html tail out.println("</body></html>"); out.flush(); out.close(); } /** * @param e * @param out */ public void writeExceptionStack(Throwable e, PrintWriter out) { out.println("<h2 class=\"a4j_debug\">Exceptions: </h2>"); Throwable error = e; int errorId = 0; String caused = "exception "; while (null != error) { out.print("<h3 onclick=\"toggle('exception" + errorId + "')\" class='exception a4j_debug'>"); writeToggleMark(out, "exception" + errorId); out.print(caused + error.getClass().getName() + " : " + error.getMessage() + "</h3>"); out.println("<div id='exception" + errorId + "' style='display: none;' class='exception'><p>Exception stack :</p><pre>"); StackTraceElement[] stackTrace = error.getStackTrace(); for (int i = 0; i < stackTrace.length; i++) { out.print(" at " + stackTrace[i].getClassName()); out.print("." + stackTrace[i].getMethodName()); out.println(" in " + stackTrace[i].getFileName() + " line " + stackTrace[i].getLineNumber()); } // error.printStackTrace(out); out.println("</pre></div>"); error = error.getCause(); caused = "caused by "; errorId++; } } /** * @param context * @param out */ public void writeContextVariables(FacesContext context, PrintWriter out) { out.print("<h2 class=\"a4j_debug\" onclick=\"toggle('variables')\">"); writeToggleMark(out, "variables"); out.println( "Faces variables: </h2><div id='variables' style='display: none;' class='variables a4j_debug'>"); writeVariables(out, context); out.println("</div>"); } /** * @param context * @param out */ public void writeComponentsTree(FacesContext context, PrintWriter out) { out.print("<h2 class=\"a4j_debug\" onclick=\"toggle('tree')\">"); writeToggleMark(out, "tree"); out.println("Component tree: </h2><div id='tree' style='display: none;' class='tree a4j_debug'><dl>"); writeComponent(context, out, context.getViewRoot(), null); out.println("</dl></div>"); } public void writeScriptAndStyle(PrintWriter out) { writeScript(out); writeStyleSheet(out); } /** * @param context * @param out * @throws FacesException */ public void writeLog(FacesContext context, PrintWriter out) throws FacesException { String logname = context.getExternalContext().getInitParameter(LOGFILE_PARAM); if (null != logname) { InternetResource logResource = InternetResourceBuilder.getInstance().createResource(this, logname); out.print("<h2 onclick=\"toggle('log')\" class=\"a4j_debug\">"); writeToggleMark(out, "log"); out.println("Faces log: </h2><div id='log' style='display: none;' class='log a4j_debug'>"); out.print("<iframe name='log' class='log' src='" + logResource.getUri(context, null) + "'><a href='src='" + logResource.getUri(context, null) + "'>Faces log file </a> </iframe>"); out.println("</div>"); } } public void writeToggleMark(PrintWriter out, String id) { out.print("<span style=\"display:none;\" id=\"" + id + "_expanded\" >- </span>"); out.print("<span style=\"display:inline;\" id=\"" + id + "_collapsed\" >+</span> "); } /** * Out component with properties and it's facets and childrens * @param context TODO * @param out * @param viewRoot */ private void writeComponent(FacesContext context, PrintWriter out, UIComponent component, String facetName) { String clientId = "_tree:" + component.getClientId(context); out.println("<dt onclick=\"toggle('" + clientId + "')\" class='tree'>"); writeToggleMark(out, clientId); // out component name if (null != facetName) { out.print("Facet:'" + facetName + "' "); } out.println("<code>" + component.getClass().getName() + "</code> Id:[" + component.getId() + "]"); out.println("</dt>"); out.println("<dd id='" + clientId + "' style='display:none;' class='tree' ><ul class='tree'>"); // out bean properties try { PropertyDescriptor propertyDescriptors[] = PropertyUtils.getPropertyDescriptors(component); for (int i = 0; i < propertyDescriptors.length; i++) { if (PropertyUtils.isReadable(component, propertyDescriptors[i].getName())) { String name = propertyDescriptors[i].getName(); ValueBinding vb = component.getValueBinding(name); if (vb != null) { writeAttribute(out, name, vb.getExpressionString()); } else { if (!IGNORE_ATTRIBUTES.contains(name)) { try { String value = BeanUtils.getProperty(component, name); writeAttribute(out, name, value); } catch (Exception e) { writeAttribute(out, name, null); } } } } } } catch (Exception e) { // Do nothing - we in error page. } // out bindings // out attributes map for (Iterator it = component.getAttributes().entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); writeAttribute(out, (String) entry.getKey(), entry.getValue()); } // out listeners out.println("</ul></dd>"); if (component.getFacetsAndChildren().hasNext()) { out.println("<dd class='tree_childs'><dl class='tree_childs'>"); // out childs of this component // facets for (Iterator facetEntry = component.getFacets().entrySet().iterator(); facetEntry.hasNext();) { Map.Entry entry = (Map.Entry) facetEntry.next(); writeComponent(context, out, (UIComponent) entry.getValue(), (String) entry.getKey()); } // childs components for (Iterator childIter = component.getChildren().iterator(); childIter.hasNext();) { UIComponent child = (UIComponent) childIter.next(); writeComponent(context, out, child, null); } out.println("</dl></dd>"); } } private void writeAttribute(PrintWriter out, String name, Object value) { if (IGNORE_ATTRIBUTES.contains(name)) return; if (name.startsWith("javax.faces.webapp.UIComponentTag.")) { name = name.substring("javax.faces.webapp.UIComponentTag.".length()); } out.print("<li>"); out.print(name); out.print("=\""); if (value != null) { if (value instanceof UIComponent) { out.print("[id:"); out.print(((UIComponent) value).getId()); out.print(']'); } else if (value instanceof MethodBinding) { out.print(((MethodBinding) value).getExpressionString()); } else if (value instanceof ValueBinding) { out.print(((ValueBinding) value).getExpressionString()); } else { out.print(value.toString()); } } else { out.print("NULL"); } out.println("\"</li>"); } private void writeVariables(PrintWriter out, FacesContext faces) { ExternalContext ctx = faces.getExternalContext(); writeVariables(out, ctx.getRequestParameterMap(), "Request Parameters"); writeVariables(out, ctx.getRequestMap(), "Request Attributes"); if (ctx.getSession(false) != null) { writeVariables(out, ctx.getSessionMap(), "Session Attributes"); } writeVariables(out, ctx.getApplicationMap(), "Application Attributes"); } private void writeVariables(PrintWriter out, Map vars, String caption) { out.print("<table><caption>"); out.print(caption); out.println( "</caption><thead><tr><th style=\"width: 10%; \">Name</th><th style=\"width: 90%; \">Value</th></tr></thead><tbody>"); boolean written = false; if (!vars.isEmpty()) { SortedMap map = new TreeMap(vars); Map.Entry entry = null; String key = null; for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) { entry = (Map.Entry) itr.next(); key = entry.getKey().toString(); if (key.indexOf('.') == -1) { out.println("<tr><td>"); out.println(key.replaceAll("<", LT).replaceAll(">", GT)); out.println("</td><td><span class='value'>"); Object value = entry.getValue(); out.println(value.toString().replaceAll("<", LT).replaceAll(">", GT)); out.println("</span>"); try { PropertyDescriptor propertyDescriptors[] = PropertyUtils.getPropertyDescriptors(value); if (propertyDescriptors.length > 0) { out.print("<div class='properties'><ul class=\'properties\'>"); for (int i = 0; i < propertyDescriptors.length; i++) { String beanPropertyName = propertyDescriptors[i].getName(); if (PropertyUtils.isReadable(value, beanPropertyName)) { out.print("<li class=\'properties\'>"); out.print(beanPropertyName + " = " + BeanUtils.getProperty(value, beanPropertyName)); out.print("</li>"); } } out.print("</ul></div>"); } } catch (Exception e) { // TODO: log exception } out.println("</td></tr>"); written = true; } } } if (!written) { out.println("<tr><td colspan=\"2\"><em>None</em></td></tr>"); } out.println("</tbody></table>"); } /** * @param out */ private void writeScript(PrintWriter out) { out.println("<script type='text/javascript' language='javascript'>\n" + "function toggle(id) {\n" + "var style = document.getElementById(id).style;\n" + "if ('block' == style.display) {\n" + "style.display = 'none';\n" + "document.getElementById(id+'_collapsed').style.display = 'inline';\n" + "document.getElementById(id+'_expanded').style.display = 'none';\n" + "} else {\n" + "style.display = 'block';\n" + "document.getElementById(id+'_collapsed').style.display = 'none';\n" + "document.getElementById(id+'_expanded').style.display = 'inline';\n" + "}\n" + "}\n\n" + "</script>"); } /** * @param out */ private void writeStyleSheet(PrintWriter out) { out.println("<style type=\'text/css\' >\n" + "div.a4j_debug, .a4j_debug span, .a4j_debug td, .a4j_debug th, .a4j_debug caption { font-family: Verdana, Arial, Sans-Serif; }\n" + ".a4j_debug li{\n" + " list-style-position : inside;\n" + "}\n" + "\n" + ".a4j_debug li, .a4j_debug pre { padding: 0; margin: 0; font-size : 12px;}\n" + ".a4j_debug ul { padding: 0 0 10 0; margin: 0; font-size : 12px;}\n" + ".a4j_debug h1 { color: #fff; background-color : #a00; font-size : 17px; padding : 7px 10px 10px 10px}\n" + "h2.a4j_debug , h2.a4j_debug span { color: #a00; font-size : 17px; padding : 0px 0px 0px 10px;}\n" + "h2.a4j_debug a { text-decoration: none; color: #a00; }\n" + ".exception { color: #000; font-size : 14px; padding : 0px 0px 0px 10px;}\n" + ".grayBox { padding: 8px; margin: 10px 0; border: 1px solid #CCC; background-color: #f9f9f9; font-size : 12px; }\n" + "#error { color: #900; font-weight: bold; font-size: medium; }\n" + "#trace, #tree, #vars { display: none; }\n" + ".a4j_debug code { font-size: medium; font-size : 14px;}\n" + "#tree dl { color: #666; }\n" + "#tree dd { font-size : 12px;}\n" + "#tree dt { border: 1px solid #DDD; padding: 2px 4px 4px 4px; border-left: 2px solid #a00; font-family: \"Courier New\", Courier, mono; font-size: small; font-size : 12px; margin-top: 2px; margin-bottom: 2px;}\n" + ".uicText { color: #999; }\n" + ".a4j_debug table { border: 1px solid #CCC; border-collapse: collapse; border-spacing: 0px; width: 100%; text-align: left; }\n" + ".a4j_debug td { border: 1px solid #CCC; font-size : 12px; vertical-align : top}\n" + ".a4j_debug thead tr th { padding: 2px; color: #030; background-color: #F9F9F9; font-size : 12px;}\n" + ".a4j_debug tbody tr td { padding: 10px 6px; }\n" + ".a4j_debug table caption { text-align: left; padding: 20 0 5 0; font-size : 12px; font-weight : bold;}\n" + ".value {font-size : 12px; font-weight : bold;}\n" + "div.log { width: 100%; height: 400px;}\n" + "iframe.log { width: 99%; height: 99%; border: 1px solid #CCC;}\n" + "</style>"); } }