package myfreemarker; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.struts2.StrutsException; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.util.ValueStack; import com.opensymphony.xwork2.util.reflection.ReflectionProvider; import freemarker.core.Environment; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateDirectiveBody; import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateException; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; public class DebugDirective implements TemplateDirectiveModel { protected ReflectionProvider reflectionProvider; @Inject public void setReflectionProvider(ReflectionProvider prov) { this.reflectionProvider = prov; } @Override public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { if (!params.isEmpty()) { throw new TemplateModelException("This debug directive doesn't allow parameters."); } if (loopVars.length != 0) { throw new TemplateModelException("This debug directive doesn't allow loop variables."); } if (body == null) { Configuration cfg = env.getConfiguration(); Template template = cfg.getTemplate("debug.ftl"); ActionContext context = ActionContext.getContext(); ValueStack stack = context.getValueStack(); context.getContainer().inject(cfg.getSharedVariable("debug")); Iterator iter = stack.getRoot().iterator(); List stackValues = new ArrayList(stack.getRoot().size()); while (iter.hasNext()) { Object o = iter.next(); Map values; try { values = reflectionProvider.getBeanMap(o); } catch (Exception e) { throw new StrutsException("Caught an exception while getting the property values of " + o, e); } stackValues.add(new DebugMapEntry(o.getClass().getName(), values)); } Map parameters = new LinkedHashMap(); parameters.put("stackValues", stackValues); Map root = new HashMap(); root.put("stack", stack); root.put("parameters", parameters); Writer writer = env.getOut(); template.process(root, writer); } else { throw new RuntimeException("debug directive do not need body"); } } private static class DebugMapEntry implements Map.Entry { private Object key; private Object value; DebugMapEntry(Object key, Object value) { this.key = key; this.value = value; } public Object getKey() { return key; } public Object getValue() { return value; } public Object setValue(Object newVal) { Object oldVal = value; value = newVal; return oldVal; } } }