001: /*
002: * Copyright 2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.myfaces.util;
017:
018: import org.apache.commons.logging.Log;
019: import org.apache.commons.logging.LogFactory;
020:
021: import javax.faces.FacesException;
022: import javax.faces.component.*;
023: import javax.faces.context.FacesContext;
024: import javax.faces.el.MethodBinding;
025: import javax.faces.el.ValueBinding;
026: import javax.faces.event.FacesListener;
027: import javax.faces.validator.Validator;
028: import java.beans.BeanInfo;
029: import java.beans.IntrospectionException;
030: import java.beans.Introspector;
031: import java.beans.PropertyDescriptor;
032: import java.io.ByteArrayOutputStream;
033: import java.io.IOException;
034: import java.io.PrintStream;
035: import java.util.HashSet;
036: import java.util.Iterator;
037: import java.util.Map;
038:
039: /**
040: * Utilities for logging.
041: *
042: * @author Manfred Geiler (latest modification by $Author: mbr $)
043: * @version $Revision: 511491 $ $Date: 2007-02-25 13:46:01 +0100 (So, 25 Feb 2007) $
044: */
045: public class DebugUtils {
046: private static final Log log = LogFactory.getLog(DebugUtils.class);
047:
048: //Attributes that should not be printed
049: private static final HashSet<String> IGNORE_ATTRIBUTES;
050: static {
051: IGNORE_ATTRIBUTES = new HashSet<String>();
052: IGNORE_ATTRIBUTES.add("attributes");
053: IGNORE_ATTRIBUTES.add("children");
054: IGNORE_ATTRIBUTES.add("childCount");
055: IGNORE_ATTRIBUTES.add("class");
056: IGNORE_ATTRIBUTES.add("facets");
057: IGNORE_ATTRIBUTES.add("facetsAndChildren");
058: IGNORE_ATTRIBUTES.add("parent");
059: IGNORE_ATTRIBUTES.add("actionListeners");
060: IGNORE_ATTRIBUTES.add("valueChangeListeners");
061: IGNORE_ATTRIBUTES.add("validators");
062: IGNORE_ATTRIBUTES.add("rowData");
063: IGNORE_ATTRIBUTES.add("javax.faces.webapp.COMPONENT_IDS");
064: IGNORE_ATTRIBUTES.add("javax.faces.webapp.FACET_NAMES");
065: IGNORE_ATTRIBUTES.add("javax.faces.webapp.CURRENT_VIEW_ROOT");
066: }
067:
068: private static final String JSF_COMPONENT_PACKAGE = "javax.faces.component.";
069: private static final String MYFACES_COMPONENT_PACKAGE = "org.apache.myfaces.component.";
070:
071: private DebugUtils() {
072: // hide from public access
073: }
074:
075: public static void assertError(boolean condition, Log log_,
076: String msg) throws FacesException {
077: if (!condition) {
078: log_.error(msg);
079: throw new FacesException(msg);
080: }
081: }
082:
083: public static void assertFatal(boolean condition, Log log_,
084: String msg) throws FacesException {
085: if (!condition) {
086: log_.fatal(msg);
087: throw new FacesException(msg);
088: }
089: }
090:
091: public static void traceView(String additionalMsg) {
092: if (log.isTraceEnabled()) {
093: FacesContext facesContext = FacesContext
094: .getCurrentInstance();
095: if (facesContext == null) {
096: log
097: .error("Cannot not print view to console (no FacesContext).");
098: return;
099: }
100: UIViewRoot viewRoot = facesContext.getViewRoot();
101: if (viewRoot == null) {
102: log
103: .error("Cannot not print view to console (no ViewRoot in FacesContext).");
104: return;
105: }
106:
107: traceView(additionalMsg, viewRoot);
108: }
109: }
110:
111: /**
112: * Be careful, when using this version of traceView:
113: * Some component properties (e.g. getRenderer) assume, that there is a
114: * valid viewRoot set in the FacesContext!
115: * @param additionalMsg
116: * @param viewRoot
117: */
118: private static void traceView(String additionalMsg,
119: UIViewRoot viewRoot) {
120: ByteArrayOutputStream baos = new ByteArrayOutputStream();
121: PrintStream ps = new PrintStream(baos);
122: if (additionalMsg != null) {
123: ps.println(additionalMsg);
124: }
125: ps.println("========================================");
126: printView(viewRoot, ps);
127: ps.println("========================================");
128: ps.close();
129: log.trace(baos.toString());
130: }
131:
132: public static void printView(UIViewRoot uiViewRoot,
133: PrintStream stream) {
134: printComponent(uiViewRoot, stream, 0, true, null);
135: }
136:
137: public static void printComponent(UIComponent comp,
138: PrintStream stream) {
139: printComponent(comp, stream, 0, false, null);
140: }
141:
142: private static void printComponent(UIComponent comp,
143: PrintStream stream, int indent,
144: boolean withChildrenAndFacets, String facetName) {
145: printIndent(stream, indent);
146: stream.print('<');
147:
148: String compType = comp.getClass().getName();
149: if (compType.startsWith(JSF_COMPONENT_PACKAGE)) {
150: compType = compType.substring(JSF_COMPONENT_PACKAGE
151: .length());
152: } else if (compType.startsWith(MYFACES_COMPONENT_PACKAGE)) {
153: compType = compType.substring(MYFACES_COMPONENT_PACKAGE
154: .length());
155: }
156: stream.print(compType);
157:
158: printAttribute(stream, "id", comp.getId());
159:
160: if (facetName != null) {
161: printAttribute(stream, "facetName", facetName);
162: }
163:
164: for (Iterator it = comp.getAttributes().entrySet().iterator(); it
165: .hasNext();) {
166: Map.Entry entry = (Map.Entry) it.next();
167: if (!"id".equals(entry.getKey())) {
168: printAttribute(stream, (String) entry.getKey(), entry
169: .getValue());
170: }
171: }
172:
173: //HACK: comp.getAttributes() only returns attributes, that are NOT backed
174: //by a corresponding component property. So, we must explicitly get the
175: //available properties by Introspection:
176: BeanInfo beanInfo;
177: try {
178: beanInfo = Introspector.getBeanInfo(comp.getClass());
179: } catch (IntrospectionException e) {
180: throw new RuntimeException(e);
181: }
182:
183: PropertyDescriptor propDescriptors[] = beanInfo
184: .getPropertyDescriptors();
185: for (int i = 0; i < propDescriptors.length; i++) {
186: if (propDescriptors[i].getReadMethod() != null) {
187: String name = propDescriptors[i].getName();
188: if (!"id".equals(name)) {
189: ValueBinding vb = comp.getValueBinding(name);
190: if (vb != null) {
191: printAttribute(stream, name, vb
192: .getExpressionString());
193: } else {
194: if (name.equals("value")
195: && comp instanceof ValueHolder) {
196: //-> localValue
197: } else if (!IGNORE_ATTRIBUTES.contains(name)) {
198: try {
199: Object value = comp.getAttributes()
200: .get(name);
201: printAttribute(stream, name, value);
202: } catch (Exception e) {
203: log.error(e);
204: printAttribute(stream, name, null);
205: }
206: }
207: }
208: }
209: }
210: }
211:
212: boolean mustClose = true;
213: boolean nestedObjects = false;
214:
215: if (comp instanceof UICommand) {
216: FacesListener[] listeners = ((UICommand) comp)
217: .getActionListeners();
218: if (listeners != null && listeners.length > 0) {
219: nestedObjects = true;
220: stream.println('>');
221: mustClose = false;
222: for (int i = 0; i < listeners.length; i++) {
223: FacesListener listener = listeners[i];
224: printIndent(stream, indent + 1);
225: stream.print('<');
226: stream.print(listener.getClass().getName());
227: stream.println("/>");
228: }
229: }
230: }
231:
232: if (comp instanceof UIInput) {
233: FacesListener[] listeners = ((UIInput) comp)
234: .getValueChangeListeners();
235: if (listeners != null && listeners.length > 0) {
236: nestedObjects = true;
237: stream.println('>');
238: mustClose = false;
239: for (int i = 0; i < listeners.length; i++) {
240: FacesListener listener = listeners[i];
241: printIndent(stream, indent + 1);
242: stream.print('<');
243: stream.print(listener.getClass().getName());
244: stream.println("/>");
245: }
246: }
247:
248: Validator[] validators = ((UIInput) comp).getValidators();
249: if (validators != null && validators.length > 0) {
250: nestedObjects = true;
251: stream.println('>');
252: mustClose = false;
253: for (int i = 0; i < validators.length; i++) {
254: Validator validator = validators[i];
255: printIndent(stream, indent + 1);
256: stream.print('<');
257: stream.print(validator.getClass().getName());
258: stream.println("/>");
259: }
260: }
261: }
262:
263: if (withChildrenAndFacets) {
264: int childCount = comp.getChildCount();
265: Map<String, UIComponent> facetsMap = comp.getFacets();
266: if (childCount > 0 || !facetsMap.isEmpty()) {
267: nestedObjects = true;
268: if (mustClose) {
269: stream.println('>');
270: mustClose = false;
271: }
272:
273: if (childCount > 0) {
274: for (Iterator it = comp.getChildren().iterator(); it
275: .hasNext();) {
276: UIComponent child = (UIComponent) it.next();
277: printComponent(child, stream, indent + 1, true,
278: null);
279: }
280: }
281:
282: for (Iterator it = facetsMap.entrySet().iterator(); it
283: .hasNext();) {
284: Map.Entry entry = (Map.Entry) it.next();
285: printComponent((UIComponent) entry.getValue(),
286: stream, indent + 1, true, (String) entry
287: .getKey());
288: }
289: }
290: }
291:
292: if (nestedObjects) {
293: if (mustClose) {
294: stream.println("/>");
295: } else {
296: printIndent(stream, indent);
297: stream.print("</");
298: stream.print(compType);
299: stream.println('>');
300: }
301: } else {
302: stream.println("/>");
303: }
304: }
305:
306: private static void printAttribute(PrintStream stream, String name,
307: Object value) {
308: if (IGNORE_ATTRIBUTES.contains(name))
309: return;
310: if (name.startsWith("javax.faces.webapp.UIComponentTag.")) {
311: name = name.substring("javax.faces.webapp.UIComponentTag."
312: .length());
313: }
314: stream.print(' ');
315: stream.print(name.toString());
316: stream.print("=\"");
317: if (value != null) {
318: if (value instanceof UIComponent) {
319: stream.print("[id:");
320: stream.print(((UIComponent) value).getId());
321: stream.print(']');
322: } else if (value instanceof MethodBinding) {
323: stream.print(((MethodBinding) value)
324: .getExpressionString());
325: } else {
326: stream.print(value.toString());
327: }
328: } else {
329: stream.print("NULL");
330: }
331: stream.print('"');
332: }
333:
334: private static void printIndent(PrintStream stream, int depth) {
335: for (int i = 0; i < depth; i++) {
336: stream.print(" ");
337: }
338: }
339:
340: public static String componentAsString(UIComponent comp) {
341: try {
342: ByteArrayOutputStream baos = new ByteArrayOutputStream();
343: printComponent(comp, new PrintStream(baos));
344: baos.close();
345: return baos.toString();
346: } catch (IOException e) {
347: throw new RuntimeException(e);
348: }
349: }
350: }
|