1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.util;
20
21 import java.beans.BeanInfo;
22 import java.beans.IntrospectionException;
23 import java.beans.Introspector;
24 import java.beans.PropertyDescriptor;
25 import java.io.ByteArrayOutputStream;
26 import java.io.IOException;
27 import java.io.PrintStream;
28 import java.util.HashSet;
29 import java.util.Map;
30 import java.util.logging.Level;
31 import java.util.logging.Logger;
32
33 import javax.el.MethodExpression;
34 import javax.el.ValueExpression;
35 import javax.faces.FacesException;
36 import javax.faces.component.UICommand;
37 import javax.faces.component.UIComponent;
38 import javax.faces.component.UIInput;
39 import javax.faces.component.UIViewRoot;
40 import javax.faces.component.ValueHolder;
41 import javax.faces.context.FacesContext;
42 import javax.faces.event.FacesListener;
43 import javax.faces.validator.Validator;
44
45
46
47
48
49
50
51 public class DebugUtils
52 {
53
54 private static final Logger log = Logger.getLogger(DebugUtils.class.getName());
55
56
57 private static final HashSet<String> IGNORE_ATTRIBUTES;
58 static
59 {
60 IGNORE_ATTRIBUTES = new HashSet<String>();
61 IGNORE_ATTRIBUTES.add("attributes");
62 IGNORE_ATTRIBUTES.add("children");
63 IGNORE_ATTRIBUTES.add("childCount");
64 IGNORE_ATTRIBUTES.add("class");
65 IGNORE_ATTRIBUTES.add("facets");
66 IGNORE_ATTRIBUTES.add("facetsAndChildren");
67 IGNORE_ATTRIBUTES.add("parent");
68 IGNORE_ATTRIBUTES.add("actionListeners");
69 IGNORE_ATTRIBUTES.add("valueChangeListeners");
70 IGNORE_ATTRIBUTES.add("validators");
71 IGNORE_ATTRIBUTES.add("rowData");
72 IGNORE_ATTRIBUTES.add("javax.faces.webapp.COMPONENT_IDS");
73 IGNORE_ATTRIBUTES.add("javax.faces.webapp.FACET_NAMES");
74 IGNORE_ATTRIBUTES.add("javax.faces.webapp.CURRENT_VIEW_ROOT");
75 }
76
77 private static final String JSF_COMPONENT_PACKAGE = "javax.faces.component.";
78 private static final String MYFACES_COMPONENT_PACKAGE = "org.apache.myfaces.component.";
79
80 private DebugUtils()
81 {
82
83 }
84
85 public static void assertError(boolean condition, Logger logger, String msg) throws FacesException
86 {
87 if (!condition)
88 {
89 logger.severe(msg);
90 throw new FacesException(msg);
91 }
92 }
93
94 public static void assertFatal(boolean condition, Logger logger, String msg) throws FacesException
95 {
96 if (!condition)
97 {
98 logger.severe(msg);
99 throw new FacesException(msg);
100 }
101 }
102
103 public static void traceView(String additionalMsg)
104 {
105 if (log.isLoggable(Level.FINEST))
106 {
107 FacesContext facesContext = FacesContext.getCurrentInstance();
108 if (facesContext == null)
109 {
110 log.severe("Cannot not print view to console (no FacesContext).");
111 return;
112 }
113 UIViewRoot viewRoot = facesContext.getViewRoot();
114 if (viewRoot == null)
115 {
116 log.severe("Cannot not print view to console (no ViewRoot in FacesContext).");
117 return;
118 }
119
120 traceView(additionalMsg, viewRoot);
121 }
122 }
123
124
125
126
127
128
129
130
131 private static void traceView(String additionalMsg, UIViewRoot viewRoot)
132 {
133 ByteArrayOutputStream baos = new ByteArrayOutputStream();
134 PrintStream ps = new PrintStream(baos);
135 if (additionalMsg != null)
136 {
137 ps.println(additionalMsg);
138 }
139 ps.println("========================================");
140 printView(viewRoot, ps);
141 ps.println("========================================");
142 ps.close();
143 log.finest(baos.toString());
144 }
145
146 public static void printView(UIViewRoot uiViewRoot, PrintStream stream)
147 {
148 printComponent(uiViewRoot, stream, 0, true, null);
149 }
150
151 public static void printComponent(UIComponent comp, PrintStream stream)
152 {
153 printComponent(comp, stream, 0, false, null);
154 }
155
156 private static void printComponent(UIComponent comp, PrintStream stream, int indent, boolean withChildrenAndFacets,
157 String facetName)
158 {
159 printIndent(stream, indent);
160 stream.print('<');
161
162 String compType = comp.getClass().getName();
163 if (compType.startsWith(JSF_COMPONENT_PACKAGE))
164 {
165 compType = compType.substring(JSF_COMPONENT_PACKAGE.length());
166 }
167 else if (compType.startsWith(MYFACES_COMPONENT_PACKAGE))
168 {
169 compType = compType.substring(MYFACES_COMPONENT_PACKAGE.length());
170 }
171 stream.print(compType);
172
173 printAttribute(stream, "id", comp.getId());
174
175 if (facetName != null)
176 {
177 printAttribute(stream, "facetName", facetName);
178 }
179
180 for (Map.Entry<String, Object> entry : comp.getAttributes().entrySet())
181 {
182 if (!"id".equals(entry.getKey()))
183 {
184 printAttribute(stream, entry.getKey(), entry.getValue());
185 }
186 }
187
188
189
190
191 BeanInfo beanInfo;
192 try
193 {
194 beanInfo = Introspector.getBeanInfo(comp.getClass());
195 }
196 catch (IntrospectionException e)
197 {
198 throw new RuntimeException(e);
199 }
200
201 if (!compType.startsWith("org.apache.myfaces.view.facelets.compiler"))
202 {
203 PropertyDescriptor propDescriptors[] = beanInfo.getPropertyDescriptors();
204 for (int i = 0; i < propDescriptors.length; i++)
205 {
206 if (propDescriptors[i].getReadMethod() != null)
207 {
208 String name = propDescriptors[i].getName();
209 if (!"id".equals(name))
210 {
211 ValueExpression ve = comp.getValueExpression(name);
212 if (ve != null)
213 {
214 printAttribute(stream, name, ve.getExpressionString());
215 }
216 else
217 {
218 if (name.equals("value") && comp instanceof ValueHolder)
219 {
220
221 }
222 else if (!IGNORE_ATTRIBUTES.contains(name))
223 {
224 try
225 {
226 Object value = comp.getAttributes().get(name);
227 printAttribute(stream, name, value);
228 }
229 catch (Exception e)
230 {
231 log.log(Level.SEVERE, e.getMessage() , e);
232 printAttribute(stream, name, null);
233 }
234 }
235 }
236 }
237 }
238 }
239 }
240
241 boolean mustClose = true;
242 boolean nestedObjects = false;
243
244 if (comp instanceof UICommand)
245 {
246 FacesListener[] listeners = ((UICommand)comp).getActionListeners();
247 if (listeners != null && listeners.length > 0)
248 {
249 nestedObjects = true;
250 stream.println('>');
251 mustClose = false;
252 for (int i = 0; i < listeners.length; i++)
253 {
254 FacesListener listener = listeners[i];
255 printIndent(stream, indent + 1);
256 stream.print('<');
257 stream.print(listener.getClass().getName());
258 stream.println("/>");
259 }
260 }
261 }
262
263 if (comp instanceof UIInput)
264 {
265 FacesListener[] listeners = ((UIInput)comp).getValueChangeListeners();
266 if (listeners != null && listeners.length > 0)
267 {
268 nestedObjects = true;
269 stream.println('>');
270 mustClose = false;
271 for (int i = 0; i < listeners.length; i++)
272 {
273 FacesListener listener = listeners[i];
274 printIndent(stream, indent + 1);
275 stream.print('<');
276 stream.print(listener.getClass().getName());
277 stream.println("/>");
278 }
279 }
280
281 Validator[] validators = ((UIInput)comp).getValidators();
282 if (validators != null && validators.length > 0)
283 {
284 nestedObjects = true;
285 stream.println('>');
286 mustClose = false;
287 for (int i = 0; i < validators.length; i++)
288 {
289 Validator validator = validators[i];
290 printIndent(stream, indent + 1);
291 stream.print('<');
292 stream.print(validator.getClass().getName());
293 stream.println("/>");
294 }
295 }
296 }
297
298 if (withChildrenAndFacets)
299 {
300 int childCount = comp.getChildCount();
301 if (childCount > 0 || comp.getFacetCount() > 0)
302 {
303 Map<String, UIComponent> facetsMap = comp.getFacets();
304 nestedObjects = true;
305 if (mustClose)
306 {
307 stream.println('>');
308 mustClose = false;
309 }
310
311 if (childCount > 0)
312 {
313 for (int i = 0; i < childCount; i++)
314 {
315 UIComponent child = comp.getChildren().get(i);
316 printComponent(child, stream, indent + 1, true, null);
317 }
318 }
319
320 for (Map.Entry<String, UIComponent> entry : facetsMap.entrySet())
321 {
322 printComponent(entry.getValue(), stream, indent + 1, true, entry.getKey());
323 }
324 }
325 }
326
327 if (nestedObjects)
328 {
329 if (mustClose)
330 {
331 stream.println("/>");
332 }
333 else
334 {
335 printIndent(stream, indent);
336 stream.print("</");
337 stream.print(compType);
338 stream.println('>');
339 }
340 }
341 else
342 {
343 stream.println("/>");
344 }
345 }
346
347 private static void printAttribute(PrintStream stream, String name, Object value)
348 {
349 if (IGNORE_ATTRIBUTES.contains(name))
350 {
351 return;
352 }
353 if (name.startsWith("javax.faces.webapp.UIComponentTag."))
354 {
355 name = name.substring("javax.faces.webapp.UIComponentTag.".length());
356 }
357 stream.print(' ');
358 stream.print(name);
359 stream.print("=\"");
360 if (value != null)
361 {
362 if (value instanceof UIComponent)
363 {
364 stream.print("[id:");
365 stream.print(((UIComponent)value).getId());
366 stream.print(']');
367 }
368 else if (value instanceof MethodExpression)
369 {
370 stream.print(((MethodExpression)value).getExpressionString());
371 }
372 else
373 {
374 stream.print(value.toString());
375 }
376 }
377 else
378 {
379 stream.print("NULL");
380 }
381 stream.print('"');
382 }
383
384 private static void printIndent(PrintStream stream, int depth)
385 {
386 for (int i = 0; i < depth; i++)
387 {
388 stream.print(" ");
389 }
390 }
391
392 public static String componentAsString(UIComponent comp)
393 {
394 try
395 {
396 ByteArrayOutputStream baos = new ByteArrayOutputStream();
397 printComponent(comp, new PrintStream(baos));
398 baos.close();
399 return baos.toString();
400 }
401 catch (IOException e)
402 {
403 throw new RuntimeException(e);
404 }
405 }
406 }