Provides several different debugging screens to provide insight into the
data behind the page.
The value of the 'debug' request parameter determines
the screen:
This interceptor only is activated when devMode is enabled in
struts.properties. The 'debug' parameter is removed from the parameter list
before the action is executed. All operations occur before the natural
Result has a chance to execute.
| Method from org.apache.struts2.interceptor.debugging.DebuggingInterceptor Detail: |
public void destroy() {
}
|
public void init() {
}
|
public String intercept(ActionInvocation inv) throws Exception {
boolean actionOnly = false;
boolean cont = true;
if (devMode) {
final ActionContext ctx = ActionContext.getContext();
String type = getParameter(DEBUG_PARAM);
ctx.getParameters().remove(DEBUG_PARAM);
if (XML_MODE.equals(type)) {
inv.addPreResultListener(
new PreResultListener() {
public void beforeResult(ActionInvocation inv, String result) {
printContext();
}
});
} else if (CONSOLE_MODE.equals(type)) {
consoleEnabled = true;
inv.addPreResultListener(
new PreResultListener() {
public void beforeResult(ActionInvocation inv, String actionResult) {
String xml = "";
if (enableXmlWithConsole) {
StringWriter writer = new StringWriter();
printContext(new PrettyPrintWriter(writer));
xml = writer.toString();
xml = xml.replaceAll("&", "&");
xml = xml.replaceAll(" >", ">");
xml = xml.replaceAll("< ", "<");
}
ActionContext.getContext().put("debugXML", xml);
FreemarkerResult result = new FreemarkerResult();
result.setFreemarkerManager(freemarkerManager);
result.setContentType("text/html");
result.setLocation("/org/apache/struts2/interceptor/debugging/console.ftl");
result.setParse(false);
try {
result.execute(inv);
} catch (Exception ex) {
LOG.error("Unable to create debugging console", ex);
}
}
});
} else if (COMMAND_MODE.equals(type)) {
ValueStack stack = (ValueStack) ctx.getSession().get(SESSION_KEY);
if (stack == null) {
//allows it to be embedded on another page
stack = (ValueStack) ctx.get(ActionContext.VALUE_STACK);
ctx.getSession().put(SESSION_KEY, stack);
}
String cmd = getParameter(EXPRESSION_PARAM);
ServletActionContext.getRequest().setAttribute("decorator", "none");
HttpServletResponse res = ServletActionContext.getResponse();
res.setContentType("text/plain");
try {
PrintWriter writer =
ServletActionContext.getResponse().getWriter();
writer.print(stack.findValue(cmd));
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
cont = false;
} else if (BROWSER_MODE.equals(type)) {
actionOnly = true;
inv.addPreResultListener(
new PreResultListener() {
public void beforeResult(ActionInvocation inv, String actionResult) {
String rootObjectExpression = getParameter(OBJECT_PARAM);
if (rootObjectExpression == null)
rootObjectExpression = "#context";
String decorate = getParameter(DECORATE_PARAM);
ValueStack stack = (ValueStack) ctx.get(ActionContext.VALUE_STACK);
Object rootObject = stack.findValue(rootObjectExpression);
try {
StringWriter writer = new StringWriter();
ObjectToHTMLWriter htmlWriter = new ObjectToHTMLWriter(writer);
htmlWriter.write(reflectionProvider, rootObject, rootObjectExpression);
String html = writer.toString();
writer.close();
stack.set("debugHtml", html);
//on the first request, response can be decorated
//but we need plain text on the other ones
if ("false".equals(decorate))
ServletActionContext.getRequest().setAttribute("decorator", "none");
FreemarkerResult result = new FreemarkerResult();
result.setFreemarkerManager(freemarkerManager);
result.setContentType("text/html");
result.setLocation("/org/apache/struts2/interceptor/debugging/browser.ftl");
result.execute(inv);
} catch (Exception ex) {
LOG.error("Unable to create debugging console", ex);
}
}
});
}
}
if (cont) {
try {
if (actionOnly) {
inv.invokeActionOnly();
return null;
} else {
return inv.invoke();
}
} finally {
if (devMode && consoleEnabled) {
final ActionContext ctx = ActionContext.getContext();
ctx.getSession().put(SESSION_KEY, ctx.get(ActionContext.VALUE_STACK));
}
}
} else {
return null;
}
}
|
protected void printContext() {
HttpServletResponse res = ServletActionContext.getResponse();
res.setContentType("text/xml");
try {
PrettyPrintWriter writer = new PrettyPrintWriter(
ServletActionContext.getResponse().getWriter());
printContext(writer);
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
Prints the current context to the response in XML format. |
protected void printContext(PrettyPrintWriter writer) {
ActionContext ctx = ActionContext.getContext();
writer.startNode(DEBUG_PARAM);
serializeIt(ctx.getParameters(), "parameters", writer,
new ArrayList< Object >());
writer.startNode("context");
String key;
Map ctxMap = ctx.getContextMap();
for (Object o : ctxMap.keySet()) {
key = o.toString();
boolean print = !ignoreKeys.contains(key);
for (String ignorePrefixe : ignorePrefixes) {
if (key.startsWith(ignorePrefixe)) {
print = false;
break;
}
}
if (print) {
serializeIt(ctxMap.get(key), key, writer, new ArrayList< Object >());
}
}
writer.endNode();
Map requestMap = (Map) ctx.get("request");
serializeIt(requestMap, "request", writer, filterValueStack(requestMap));
serializeIt(ctx.getSession(), "session", writer, new ArrayList< Object >());
ValueStack stack = (ValueStack) ctx.get(ActionContext.VALUE_STACK);
serializeIt(stack.getRoot(), "valueStack", writer, new ArrayList< Object >());
writer.endNode();
}
Prints the current request to the existing writer. |
protected void serializeIt(Object bean,
String name,
PrettyPrintWriter writer,
List<Object> stack) {
writer.flush();
// Check stack for this object
if ((bean != null) && (stack.contains(bean))) {
if (LOG.isInfoEnabled()) {
LOG.info("Circular reference detected, not serializing object: "
+ name);
}
return;
} else if (bean != null) {
// Push object onto stack.
// Don't push null objects ( handled below)
stack.add(bean);
}
if (bean == null) {
return;
}
String clsName = bean.getClass().getName();
writer.startNode(name);
// It depends on the object and it's value what todo next:
if (bean instanceof Collection) {
Collection col = (Collection) bean;
// Iterate through components, and call ourselves to process
// elements
for (Object aCol : col) {
serializeIt(aCol, "value", writer, stack);
}
} else if (bean instanceof Map) {
Map< Object, Object > map = (Map) bean;
// Loop through keys and call ourselves
for (Map.Entry< Object, Object > entry : map.entrySet()) {
Object objValue = entry.getValue();
serializeIt(objValue, entry.getKey().toString(), writer, stack);
}
} else if (bean.getClass().isArray()) {
// It's an array, loop through it and keep calling ourselves
for (int i = 0; i < Array.getLength(bean); i++) {
serializeIt(Array.get(bean, i), "arrayitem", writer, stack);
}
} else {
if (clsName.startsWith("java.lang")) {
writer.setValue(bean.toString());
} else {
// Not java.lang, so we can call ourselves with this object's
// values
try {
BeanInfo info = Introspector.getBeanInfo(bean.getClass());
PropertyDescriptor[] props = info.getPropertyDescriptors();
for (PropertyDescriptor prop : props) {
String n = prop.getName();
Method m = prop.getReadMethod();
// Call ourselves with the result of the method
// invocation
if (m != null) {
serializeIt(m.invoke(bean), n, writer, stack);
}
}
} catch (Exception e) {
LOG.error(e.toString(), e);
}
}
}
writer.endNode();
// Remove object from stack
stack.remove(bean);
}
Recursive function to serialize objects to XML. Currently it will
serialize Collections, maps, Arrays, and JavaBeans. It maintains a stack
of objects serialized already in the current functioncall. This is used
to avoid looping (stack overflow) of circular linked objects. Struts and
XWork objects are ignored. |
public void setDevMode(String mode) {
this.devMode = "true".equals(mode);
}
|
public void setEnableXmlWithConsole(boolean enableXmlWithConsole) {
this.enableXmlWithConsole = enableXmlWithConsole;
}
|
public void setFreemarkerManager(FreemarkerManager mgr) {
this.freemarkerManager = mgr;
}
|
public void setReflectionProvider(ReflectionProvider reflectionProvider) {
this.reflectionProvider = reflectionProvider;
}
|