
com.opensymphony.xwork2.util.CompoundRootAccessor Maven / Gradle / Ivy
/*
* Copyright (c) 2002-2006 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.xwork2.util;
import ognl.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.opensymphony.xwork2.XWorkException;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.util.*;
/**
* A stack that is able to call methods on objects in the stack.
*
* @author $Author: mrdon $
* @author Rainer Hermanns
* @version $Revision: 1194 $
*/
public class CompoundRootAccessor implements PropertyAccessor, MethodAccessor, ClassResolver {
private final static Log log = LogFactory.getLog(CompoundRootAccessor.class);
private static Map invalidMethods = new HashMap();
public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException {
CompoundRoot root = (CompoundRoot) target;
OgnlContext ognlContext = (OgnlContext) context;
for (Iterator iterator = root.iterator(); iterator.hasNext();) {
Object o = iterator.next();
if (o == null) {
continue;
}
try {
if (OgnlRuntime.hasSetProperty(ognlContext, o, name)) {
OgnlRuntime.setProperty(ognlContext, o, name, value);
return;
} else if (o instanceof Map) {
Map map = (Map) o;
map.put(name, value);
return;
}
// } catch (OgnlException e) {
// if (e.getReason() != null) {
// final String msg = "Caught an Ognl exception while setting property " + name;
// log.error(msg, e);
// throw new RuntimeException(msg, e.getReason());
// }
} catch (IntrospectionException e) {
// this is OK if this happens, we'll just keep trying the next
}
}
Boolean reportError = (Boolean) context.get(ValueStack.REPORT_ERRORS_ON_NO_PROP);
final String msg = "No object in the CompoundRoot has a publicly accessible property named '" + name + "' (no setter could be found).";
if ((reportError != null) && (reportError.booleanValue())) {
throw new XWorkException(msg);
} else {
log.debug(msg);
}
}
public Object getProperty(Map context, Object target, Object name) throws OgnlException {
CompoundRoot root = (CompoundRoot) target;
OgnlContext ognlContext = (OgnlContext) context;
if (name instanceof Integer) {
Integer index = (Integer) name;
return root.cutStack(index.intValue());
} else if (name instanceof String) {
if ("top".equals(name)) {
if (root.size() > 0) {
return root.get(0);
} else {
return null;
}
}
for (Iterator iterator = root.iterator(); iterator.hasNext();) {
Object o = iterator.next();
if (o == null) {
continue;
}
try {
if ((OgnlRuntime.hasGetProperty(ognlContext, o, name)) || ((o instanceof Map) && ((Map) o).containsKey(name)))
{
return OgnlRuntime.getProperty(ognlContext, o, name);
}
} catch (OgnlException e) {
if (e.getReason() != null) {
final String msg = "Caught an Ognl exception while getting property " + name;
throw new XWorkException(msg, e);
}
} catch (IntrospectionException e) {
// this is OK if this happens, we'll just keep trying the next
}
}
return null;
} else {
return null;
}
}
public Object callMethod(Map context, Object target, String name, Object[] objects) throws MethodFailedException {
CompoundRoot root = (CompoundRoot) target;
if ("describe".equals(name)) {
Object v;
if (objects != null && objects.length == 1) {
v = objects[0];
} else {
v = root.get(0);
}
if (v instanceof Collection || v instanceof Map || v.getClass().isArray()) {
return v.toString();
}
try {
Map descriptors = OgnlRuntime.getPropertyDescriptors(v.getClass());
int maxSize = 0;
for (Iterator iterator = descriptors.keySet().iterator(); iterator.hasNext();) {
String pdName = (String) iterator.next();
if (pdName.length() > maxSize) {
maxSize = pdName.length();
}
}
SortedSet set = new TreeSet();
StringBuffer sb = new StringBuffer();
for (Iterator iterator = descriptors.values().iterator(); iterator.hasNext();) {
PropertyDescriptor pd = (PropertyDescriptor) iterator.next();
sb.append(pd.getName()).append(": ");
int padding = maxSize - pd.getName().length();
for (int i = 0; i < padding; i++) {
sb.append(" ");
}
sb.append(pd.getPropertyType().getName());
set.add(sb.toString());
sb = new StringBuffer();
}
sb = new StringBuffer();
for (Iterator iterator = set.iterator(); iterator.hasNext();) {
String s = (String) iterator.next();
sb.append(s).append("\n");
}
return sb.toString();
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (OgnlException e) {
e.printStackTrace();
}
return null;
}
for (Iterator iterator = root.iterator(); iterator.hasNext();) {
Object o = iterator.next();
if (o == null) {
continue;
}
Class clazz = o.getClass();
Class[] argTypes = getArgTypes(objects);
CompoundRootAccessor.MethodCall mc = null;
if (argTypes != null) {
mc = new CompoundRootAccessor.MethodCall(clazz, name, argTypes);
}
if ((argTypes == null) || !invalidMethods.containsKey(mc)) {
try {
Object value = OgnlRuntime.callMethod((OgnlContext) context, o, name, name, objects);
if (value != null) {
return value;
}
} catch (OgnlException e) {
// try the next one
Throwable reason = e.getReason();
if ((mc != null) && (reason != null) && (reason.getClass() == NoSuchMethodException.class)) {
invalidMethods.put(mc, Boolean.TRUE);
} else if (reason != null) {
throw new MethodFailedException(o, name, e.getReason());
}
}
}
}
return null;
}
public Object callStaticMethod(Map transientVars, Class aClass, String s, Object[] objects) throws MethodFailedException {
return null;
}
public Class classForName(String className, Map context) throws ClassNotFoundException {
Object root = Ognl.getRoot(context);
try {
if (root instanceof CompoundRoot) {
if (className.startsWith("vs")) {
CompoundRoot compoundRoot = (CompoundRoot) root;
if (className.equals("vs")) {
return compoundRoot.peek().getClass();
}
int index = Integer.parseInt(className.substring(2));
return compoundRoot.get(index - 1).getClass();
}
}
} catch (Exception e) {
// just try the old fashioned way
}
return Thread.currentThread().getContextClassLoader().loadClass(className);
}
private Class[] getArgTypes(Object[] args) {
if (args == null) {
return new Class[0];
}
Class[] classes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
classes[i] = (arg != null) ? arg.getClass() : Object.class;
}
return classes;
}
static class MethodCall {
Class clazz;
String name;
Class[] args;
int hash;
public MethodCall(Class clazz, String name, Class[] args) {
this.clazz = clazz;
this.name = name;
this.args = args;
this.hash = clazz.hashCode() + name.hashCode();
for (int i = 0; i < args.length; i++) {
Class arg = args[i];
hash += arg.hashCode();
}
}
public boolean equals(Object obj) {
MethodCall mc = (CompoundRootAccessor.MethodCall) obj;
return (mc.clazz.equals(clazz) && mc.name.equals(name) && Arrays.equals(mc.args, args));
}
public int hashCode() {
return hash;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy