Java tutorial
/* Copyright c 2005-2012. * Licensed under GNU LESSER General Public License, Version 3. * http://www.gnu.org/licenses */ package org.beangle.struts2.view.component; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.util.LinkedHashMap; import java.util.Map; import java.util.Stack; import org.apache.commons.lang.StringUtils; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsException; import org.apache.struts2.util.FastByteArrayOutputStream; import org.apache.struts2.views.util.ContextUtil; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import com.opensymphony.xwork2.util.TextParseUtil; import com.opensymphony.xwork2.util.ValueStack; /** * <li>remove actionMapper\determineActionURL\determineNamespace</li> <li>remove * copy parameter</li> * * @author chaostone */ public class Component { public static final String COMPONENT_STACK = "b__component_stack"; protected ValueStack stack; protected Map<String, Object> parameters; /** * Constructor. * * @param stack * OGNL value stack. */ public Component(ValueStack stack) { this.stack = stack; this.parameters = new LinkedHashMap<String, Object>(); getComponentStack().push(this); } /** * Gets the name of this component. * * @return the name of this component. */ private String getComponentName() { Class<?> c = getClass(); String name = c.getName(); int dot = name.lastIndexOf('.'); return name.substring(dot + 1).toLowerCase(); } /** * Gets the component stack of this component. * * @return the component stack of this component, never <tt>null</tt>. */ protected Stack<Component> getComponentStack() { @SuppressWarnings("unchecked") Stack<Component> componentStack = (Stack<Component>) stack.getContext().get(COMPONENT_STACK); if (componentStack == null) { componentStack = new Stack<Component>(); stack.getContext().put(COMPONENT_STACK, componentStack); } return componentStack; } /** * Callback for the start tag of this component. Should the body be * evaluated? * * @param writer * the output writer. * @return true if the body should be evaluated */ public boolean start(Writer writer) { return true; } /** * Callback for the end tag of this component. Should the body be evaluated * again? * <p/> * <b>NOTE:</b> will pop component stack. * * @param writer * the output writer. * @param body * the rendered body. * @return true if the body should be evaluated again */ public boolean end(Writer writer, String body) { return end(writer, body, true); } /** * Callback for the start tag of this component. Should the body be * evaluated again? * <p/> * <b>NOTE:</b> has a parameter to determine to pop the component stack. * * @param writer * the output writer. * @param body * the rendered body. * @param popComponentStack * should the component stack be popped? * @return true if the body should be evaluated again */ protected boolean end(Writer writer, String body, boolean popComponentStack) { assert (body != null); try { writer.write(body); } catch (IOException e) { throw new StrutsException("IOError while writing the body: " + e.getMessage(), e); } if (popComponentStack) { popComponentStack(); } return false; } /** * Pops the component stack. */ protected void popComponentStack() { getComponentStack().pop(); } /** * Finds the nearest ancestor of this component stack. * * @param clazz * the class to look for, or if assignable from. * @return the component if found, <tt>null</tt> if not. */ @SuppressWarnings("unchecked") protected <T extends Component> T findAncestor(Class<T> clazz) { Stack<? extends Component> componentStack = getComponentStack(); int currPosition = componentStack.search(this); if (currPosition >= 0) { int start = componentStack.size() - currPosition - 1; // for (int i = componentStack.size() - 2; i >= 0; i--) { for (int i = start; i >= 0; i--) { Component component = componentStack.get(i); if (clazz.isAssignableFrom(component.getClass()) && component != this) { return (T) component; } } } return null; } /** * Evaluates the OGNL stack to find a String value. * * @param expr * OGNL expression. * @return the String value found. */ protected String findString(String expr) { return (String) findValue(expr, String.class); } /** * Evaluates the OGNL stack to find a String value. * <p/> * If the given expression is <tt>null</tt/> a error is logged and a * <code>RuntimeException</code> is thrown constructed with a messaged based * on the given field and errorMsg paramter. * * @param expr * OGNL expression. * @param field * field name used when throwing <code>RuntimeException</code>. * @param errorMsg * error message used when throwing <code>RuntimeException</code> * . * @return the String value found. * @throws StrutsException * is thrown in case of expression is <tt>null</tt>. */ protected String findString(String expr, String field, String errorMsg) { if (expr == null) { throw fieldError(field, errorMsg, null); } else { return findString(expr); } } /** * Constructs a <code>RuntimeException</code> based on the given * information. * <p/> * A message is constructed and logged at ERROR level before being returned * as a <code>RuntimeException</code>. * * @param field * field name used when throwing <code>RuntimeException</code>. * @param errorMsg * error message used when throwing <code>RuntimeException</code> * . * @param e * the caused exception, can be <tt>null</tt>. * @return the constructed <code>StrutsException</code>. */ protected StrutsException fieldError(String field, String errorMsg, Exception e) { String msg = "tag '" + getComponentName() + "', field '" + field + (parameters != null && parameters.containsKey("name") ? "', name '" + parameters.get("name") : "") + "': " + errorMsg; throw new StrutsException(msg, e); } /** * Finds a value from the OGNL stack based on the given expression. Will * always evaluate <code>expr</code> against stack except when * <code>expr</code> is null. If altsyntax (%{...}) is applied, simply strip * it off. * * @param expr * the expression. Returns <tt>null</tt> if expr is null. * @return the value, <tt>null</tt> if not found. */ protected Object findValue(String expr) { if (expr == null) { return null; } expr = stripExpressionIfAltSyntax(expr); return stack.findValue(expr, false); } /** * If altsyntax (%{...}) is applied, simply strip the "%{" and "}" off. * * @param expr * the expression (must be not null) * @return the stripped expression if altSyntax is enabled. Otherwise the * parameter expression is returned as is. */ protected String stripExpressionIfAltSyntax(String expr) { return stripExpressionIfAltSyntax(stack, expr); } /** * If altsyntax (%{...}) is applied, simply strip the "%{" and "}" off. * * @param stack * the ValueStack where the context value is searched for. * @param expr * the expression (must be not null) * @return the stripped expression if altSyntax is enabled. Otherwise the * parameter expression is returned as is. */ public static String stripExpressionIfAltSyntax(ValueStack stack, String expr) { if (altSyntax(stack)) { // does the expression start with %{ and end with }? if so, just cut // it off! if (expr.startsWith("%{") && expr.endsWith("}")) { return expr.substring(2, expr.length() - 1); } } return expr; } /** * Is the altSyntax enabled? [TRUE] * <p/> * * @param stack * the ValueStack where the context value is searched for. * @return true if altSyntax is activated. False otherwise. See * <code>struts.properties</code> where the altSyntax flag is * defined. */ public static boolean altSyntax(ValueStack stack) { return ContextUtil.isUseAltSyntax(stack.getContext()); } /** * Is the altSyntax enabled? [TRUE] * <p/> * See <code>struts.properties</code> where the altSyntax flag is defined. */ public boolean altSyntax() { return altSyntax(stack); } /** * Adds the sorrounding %{ } to the expression for proper processing. * * @param expr * the expression. * @return the modified expression if altSyntax is enabled, or the parameter * expression otherwise. */ protected String completeExpressionIfAltSyntax(String expr) { if (altSyntax()) { return "%{" + expr + "}"; } return expr; } /** * This check is needed for backwards compatibility with 2.1.x * * @param expr * the expression. * @return the found string if altSyntax is enabled. The parameter * expression otherwise. */ protected String findStringIfAltSyntax(String expr) { if (altSyntax()) { return findString(expr); } return expr; } /** * Evaluates the OGNL stack to find an Object value. * <p/> * Function just like <code>findValue(String)</code> except that if the * given expression is <tt>null</tt/> a error is logged and a * <code>RuntimeException</code> is thrown constructed with a messaged based * on the given field and errorMsg paramter. * * @param expr * OGNL expression. * @param field * field name used when throwing <code>RuntimeException</code>. * @param errorMsg * error message used when throwing <code>RuntimeException</code> * . * @return the Object found, is never <tt>null</tt>. * @throws StrutsException * is thrown in case of not found in the OGNL stack, or * expression is <tt>null</tt>. */ protected Object findValue(String expr, String field, String errorMsg) { if (expr == null) { throw fieldError(field, errorMsg, null); } else { Object value = null; Exception problem = null; try { value = findValue(expr); } catch (Exception e) { problem = e; } if (value == null) { throw fieldError(field, errorMsg, problem); } return value; } } /** * Evaluates the OGNL stack to find an Object of the given type. Will * evaluate <code>expr</code> the portion wrapped with altSyntax (%{...}) * against stack when altSyntax is on, else the whole <code>expr</code> is * evaluated against the stack. * <p/> * This method only supports the altSyntax. So this should be set to true. * * @param expr * OGNL expression. * @param toType * the type expected to find. * @return the Object found, or <tt>null</tt> if not found. */ protected Object findValue(String expr, Class<?> toType) { if (altSyntax() && toType == String.class) { return TextParseUtil.translateVariables('%', expr, stack); } else { expr = stripExpressionIfAltSyntax(expr); return stack.findValue(expr, toType, false); } } /** * Constructs a string representation of the given exception. * * @param t * the exception * @return the exception as a string. */ protected String toString(Throwable t) { FastByteArrayOutputStream bout = new FastByteArrayOutputStream(); PrintWriter wrt = new PrintWriter(bout); t.printStackTrace(wrt); wrt.close(); return bout.toString(); } /** * Gets the parameters. * * @return the parameters. Is never <tt>null</tt>. */ public Map<String, Object> getParameters() { return parameters; } /** * Adds all the given parameters to this component's own parameters. * * @param params * the parameters to add. */ public void addAllParameters(Map<String, Object> params) { parameters.putAll(params); } /** * Adds the given key and value to this component's own parameter. * <p/> * If the provided key is <tt>null</tt> nothing happens. If the provided * value is <tt>null</tt> any existing parameter with the given key name is * removed. * * @param key * the key of the new parameter to add. * @param value * the value assoicated with the key. */ public void addParameter(String key, Object value) { if (key != null) { Map<String, Object> params = getParameters(); if (value == null) { params.remove(key); } else { params.put(key, value); } } } /** * Overwrite to set if body shold be used. * * @return always false for this component. */ public boolean usesBody() { return false; } public <T> T getBean(Class<T> cls) { try { ApplicationContext ctx = WebApplicationContextUtils .getWebApplicationContext(ServletActionContext.getServletContext()); String name = StringUtils.uncapitalize(StringUtils.substringAfterLast(cls.getName(), ".")); @SuppressWarnings("unchecked") T t = (T) ctx.getBean(name); return t; } catch (Exception e) { e.printStackTrace(); return null; } } }