WW-4166 Improves way of discovering tag's attributes

This commit is contained in:
Lukasz Lenart
2014-08-04 21:16:10 +02:00
parent 8aa4fe8606
commit 1143462048
2 changed files with 33 additions and 37 deletions
@@ -25,6 +25,8 @@ import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.AnnotationUtils;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsException;
@@ -43,9 +45,12 @@ import java.io.PrintWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Base class to extend for UI components.
@@ -55,8 +60,15 @@ import java.util.Stack;
*/
public class Component {
private static final Logger LOG = LoggerFactory.getLogger(Component.class);
public static final String COMPONENT_STACK = "__component_stack";
/**
* Caches information about common tag's attributes to reduce scanning for annotation @StrutsTagAttribute
*/
protected static ConcurrentMap<Class<?>, Collection<String>> standardAttributesMap = new ConcurrentHashMap<Class<?>, Collection<String>>();
protected ValueStack stack;
protected Map parameters;
protected ActionMapper actionMapper;
@@ -502,13 +514,24 @@ public class Component {
* @return true if attribute with the same name was already defined
*/
public boolean isValidTagAttribute(String attrName) {
Collection<Method> annotatedMethods = AnnotationUtils.getAnnotatedMethods(getClass(), StrutsTagAttribute.class);
for (Method annotatedMethod : annotatedMethods) {
if (annotatedMethod.getName().contains(StringUtils.capitalize(attrName))) {
return true;
return getStandardAttributes().contains(attrName);
}
/**
* If needed caches all methods annotated by given annotation to avoid further scans
*/
protected Collection<String> getStandardAttributes() {
Class clz = getClass();
Collection<String> standardAttributes = standardAttributesMap.get(clz);
if (standardAttributes == null) {
Collection<Method> methods = AnnotationUtils.getAnnotatedMethods(clz, StrutsTagAttribute.class);
standardAttributes = new HashSet<String>(methods.size());
for(Method m : methods) {
standardAttributes.add(StringUtils.uncapitalize(m.getName().substring(3)));
}
standardAttributesMap.putIfAbsent(clz, standardAttributes);
}
return false;
return standardAttributes;
}
}
@@ -517,9 +517,6 @@ public abstract class UIBean extends Component {
protected String uiThemeExpansionToken;
protected TemplateEngineManager templateEngineManager;
// dynamic attributes support for tags used with FreeMarker templates
protected static ConcurrentMap<Class, Set<String>> standardAttributesMap = new ConcurrentHashMap<Class, Set<String>>();
@Inject(StrutsConstants.STRUTS_UI_TEMPLATEDIR)
public void setDefaultTemplateDir(String dir) {
this.defaultTemplateDir = dir;
@@ -1271,40 +1268,16 @@ public abstract class UIBean extends Component {
/**
* supports dynamic attributes for freemarker ui tags
* @see https://issues.apache.org/jira/browse/WW-3174
* @see https://issues.apache.org/jira/browse/WW-4166
*/
public void copyParams(Map params) {
super.copyParams(params);
Set<String> standardAttributes = getStandardAttributes();
public void copyParams(Map params) {
super.copyParams(params);
for (Object o : params.entrySet()) {
Map.Entry entry = (Map.Entry) o;
String key = (String) entry.getKey();
if (!key.equals("dynamicAttributes") && !standardAttributes.contains(key)){
if(!isValidTagAttribute(key) && !key.equals("dynamicAttributes"))
dynamicAttributes.put(key, entry.getValue());
}
}
}
protected Set<String> getStandardAttributes() {
Class clz = getClass();
Set<String> standardAttributes = standardAttributesMap.get(clz);
if (standardAttributes == null) {
standardAttributes = new HashSet<String>();
while (clz != null) {
for (Field f : clz.getDeclaredFields()) {
if (Modifier.isProtected(f.getModifiers())
&& (f.getType().equals(String.class) || clz.equals(ListUIBean.class)
&& f.getName().equals("list")))
standardAttributes.add(f.getName());
}
if (clz.equals(UIBean.class)) {
break;
} else {
clz = clz.getSuperclass();
}
}
standardAttributesMap.putIfAbsent(clz, standardAttributes);
}
return standardAttributes;
}
}
}