alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Struts example source code file (DebuggingInterceptor.java)

This example Struts source code file (DebuggingInterceptor.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Struts tags/keywords

arraylist, bean, exception, freemarkerresult, io, javabean, map, map, object, object, preresultlistener, prettyprintwriter, reflection, request, string, string, stringwriter, util, valuestack, valuestack

The Struts DebuggingInterceptor.java source code

/*
 * $Id: DebuggingInterceptor.java 1065735 2011-01-31 20:00:58Z jafl $
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.struts2.interceptor.debugging;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.FilterDispatcher;
import org.apache.struts2.views.freemarker.FreemarkerManager;
import org.apache.struts2.views.freemarker.FreemarkerResult;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;

/**
 * <!-- START SNIPPET: description -->
 * Provides several different debugging screens to provide insight into the
 * data behind the page.
 * <!-- END SNIPPET: description -->
 * The value of the 'debug' request parameter determines
 * the screen:
 * <!-- START SNIPPET: parameters -->
 * <ul>
 * <li> xml - Dumps the parameters, context, session, and value
 * stack as an XML document.</li>
 * <li> 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.</li>
 * <li> command - Tests an OGNL expression and returns the
 * string result. Only used by the OGNL console.</li>
 * <li>browser Shows field values of an object specified in the 
 * <code>object parameter (#context by default). When the object
 * parameters is set, the '#' character needs to be escaped to '%23'. Like
 * debug=browser&object=%23parameters</li>
 * </ul>
 * <!-- END SNIPPET: parameters -->
 * <p/>
 *  Example:
 * <!-- START SNIPPET: example -->
 *  http://localhost:8080/Welcome.action?debug=xml
 * <!-- END SNIPPET: example -->
 * <p/>
 * <!-- START SNIPPET: remarks -->
 * 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.
 * <!-- END SNIPPET: remarks -->
 */
public class DebuggingInterceptor implements Interceptor {

    private static final long serialVersionUID = -3097324155953078783L;

    private final static Logger LOG = LoggerFactory.getLogger(DebuggingInterceptor.class);

    private String[] ignorePrefixes = new String[]{"org.apache.struts.",
            "com.opensymphony.xwork2.", "xwork."};
    private String[] _ignoreKeys = new String[]{"application", "session",
            "parameters", "request"};
    private HashSet<String> ignoreKeys = new HashSet(Arrays.asList(_ignoreKeys));

    private final static String XML_MODE = "xml";
    private final static String CONSOLE_MODE = "console";
    private final static String COMMAND_MODE = "command";
    private final static String BROWSER_MODE = "browser";

    private final static String SESSION_KEY = "org.apache.struts2.interceptor.debugging.VALUE_STACK";

    private final static String DEBUG_PARAM = "debug";
    private final static String OBJECT_PARAM = "object";
    private final static String EXPRESSION_PARAM = "expression";
    private final static String DECORATE_PARAM = "decorate";

    private boolean enableXmlWithConsole = false;
    
    private boolean devMode;
    private FreemarkerManager freemarkerManager;
    
    private boolean consoleEnabled = false;
    private ReflectionProvider reflectionProvider;

    @Inject(StrutsConstants.STRUTS_DEVMODE)
    public void setDevMode(String mode) {
        this.devMode = "true".equals(mode);
    }
    
    @Inject
    public void setFreemarkerManager(FreemarkerManager mgr) {
        this.freemarkerManager = mgr;
    }
    
    @Inject
    public void setReflectionProvider(ReflectionProvider reflectionProvider) {
        this.reflectionProvider = reflectionProvider;
    }

    /**
     * Unused.
     */
    public void init() {
    }


    /**
     * Unused.
     */
    public void destroy() {
    }


    /*
     * (non-Javadoc)
     *
     * @see com.opensymphony.xwork2.interceptor.Interceptor#invoke(com.opensymphony.xwork2.ActionInvocation)
     */
    public String intercept(ActionInvocation inv) throws Exception {
        boolean actionOnly = false;
        boolean cont = true;
        Boolean devModeOverride = FilterDispatcher.getDevModeOverride();
        boolean devMode = devModeOverride != null ? devModeOverride.booleanValue() : this.devMode;
        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;
        }
    }


    /**
     * Gets a single string from the request parameters
     *
     * @param key The key
     * @return The parameter value
     */
    private String getParameter(String key) {
        String[] arr = (String[]) ActionContext.getContext().getParameters().get(key);
        if (arr != null && arr.length > 0) {
            return arr[0];
        }
        return null;
    }


    /**
     * Prints the current context to the response in XML format.
     */
    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 request to the existing writer.
     *
     * @param writer The XML writer
     */
    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();
    }


    /**
     * 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).
     */
    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);
    }


    /**
     * @param enableXmlWithConsole the enableXmlWithConsole to set
     */
    public void setEnableXmlWithConsole(boolean enableXmlWithConsole) {
        this.enableXmlWithConsole = enableXmlWithConsole;
    }

    
    private List<Object> filterValueStack(Map requestMap) {
    	List<Object> filter = new ArrayList();
    	Object valueStack = requestMap.get("struts.valueStack");
    	if(valueStack != null) {
    		filter.add(valueStack);
    	}
    	return filter;
    }


}



Other Struts examples (source code examples)

Here is a short list of links related to this Struts DebuggingInterceptor.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.