FileDocCategorySizeDatePackage
DebuggingInterceptor.javaAPI DocExample14752Mon Jul 23 13:26:52 BST 2007org.apache.struts2.interceptor.debugging

DebuggingInterceptor

public class DebuggingInterceptor extends Object implements com.opensymphony.xwork2.interceptor.Interceptor
Provides several different debugging screens to provide insight into the data behind the page. The value of the 'debug' request parameter determines the screen:
  • xml - Dumps the parameters, context, session, and value stack as an XML document.
  • console - Shows a popup 'OGNL Console' that allows the user to test OGNL expressions against the value stack. The XML data from the 'xml' mode is inserted at the top of the page.
  • command - Tests an OGNL expression and returns the string result. Only used by the OGNL console.

Example: http://localhost:8080/Welcome.action?debug=xml

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.

Fields Summary
private static final long
serialVersionUID
private static final Log
log
private String[]
ignorePrefixes
private String[]
_ignoreKeys
private HashSet
ignoreKeys
private static final String
XML_MODE
private static final String
CONSOLE_MODE
private static final String
COMMAND_MODE
private static final String
SESSION_KEY
private static final String
DEBUG_PARAM
private static final String
EXPRESSION_PARAM
private boolean
enableXmlWithConsole
private boolean
devMode
private org.apache.struts2.views.freemarker.FreemarkerManager
freemarkerManager
private boolean
consoleEnabled
Constructors Summary
Methods Summary
public voiddestroy()
Unused.

    
private java.lang.StringgetParameter(java.lang.String key)
Gets a single string from the request parameters

param
key The key
return
The parameter value

        String[] arr = (String[]) ActionContext.getContext().getParameters().get(key);
        if (arr != null && arr.length > 0) {
            return arr[0];
        }
        return null;
    
public voidinit()
Unused.

    
public java.lang.Stringintercept(com.opensymphony.xwork2.ActionInvocation inv)


        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);
                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;
            }
        }
        if (cont) {
            try {
                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 voidprintContext()
Prints the current context to the response in XML format.

        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();
        }
    
protected voidprintContext(PrettyPrintWriter writer)
Prints the current request to the existing writer.

param
writer The XML 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();
        serializeIt(ctx.getSession(), "request", writer, new ArrayList<Object>());
        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();
    
protected voidserializeIt(java.lang.Object bean, java.lang.String name, PrettyPrintWriter writer, java.util.List stack)
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.

param
bean The object you want serialized.
param
name The name of the object, used for element <name/>
param
writer The XML writer
param
stack List of objects we're serializing since the first calling of this function (to prevent looping on circular references).

        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 map = (Map) bean;

            // Loop through keys and call ourselves
            for (Object key : map.keySet()) {
                Object Objvalue = map.get(key);
                serializeIt(Objvalue, key.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, e);
                }
            }
        }

        writer.endNode();

        // Remove object from stack
        stack.remove(bean);
    
public voidsetDevMode(java.lang.String mode)


    
        
        this.devMode = "true".equals(mode);
    
public voidsetEnableXmlWithConsole(boolean enableXmlWithConsole)

param
enableXmlWithConsole the enableXmlWithConsole to set

        this.enableXmlWithConsole = enableXmlWithConsole;
    
public voidsetFreemarkerManager(org.apache.struts2.views.freemarker.FreemarkerManager mgr)

        this.freemarkerManager = mgr;