001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.xwork.util;
006:
007: import ognl.MethodFailedException;
008: import ognl.ObjectMethodAccessor;
009: import ognl.OgnlContext;
010: import ognl.OgnlRuntime;
011: import ognl.PropertyAccessor;
012:
013: import java.beans.PropertyDescriptor;
014: import java.util.Collection;
015: import java.util.Map;
016:
017: /**
018: * Allows methods to be executed under normal cirumstances, except when {@link #DENY_METHOD_EXECUTION}
019: * is in the action context with a value of true.
020: *
021: * @author Patrick Lightbody
022: */
023: public class XWorkMethodAccessor extends ObjectMethodAccessor {
024:
025: public static final String DENY_METHOD_EXECUTION = "xwork.MethodAccessor.denyMethodExecution";
026: public static final String DENY_INDEXED_ACCESS_EXECUTION = "xwork.IndexedPropertyAccessor.denyMethodExecution";
027:
028: public Object callMethod(Map context, Object object, String string,
029: Object[] objects) throws MethodFailedException {
030:
031: //Collection property accessing
032: //this if statement ensures that ognl
033: //statements of the form someBean.mySet('keyPropVal')
034: //return the set element with value of the keyProp given
035:
036: if (objects.length == 1 && context instanceof OgnlContext) {
037: try {
038: OgnlContext ogContext = (OgnlContext) context;
039: if (OgnlRuntime.hasSetProperty(ogContext, object,
040: string)) {
041: PropertyDescriptor descriptor = OgnlRuntime
042: .getPropertyDescriptor(object.getClass(),
043: string);
044: Class propertyType = descriptor.getPropertyType();
045: if ((Collection.class)
046: .isAssignableFrom(propertyType)) {
047: //go directly through OgnlRuntime here
048: //so that property strings are not cleared
049: //i.e. OgnlUtil should be used initially, OgnlRuntime
050: //thereafter
051:
052: Object propVal = OgnlRuntime.getProperty(
053: ogContext, object, string);
054: //use the Collection property accessor instead of the individual property accessor, because
055: //in the case of Lists otherwise the index property could be used
056: PropertyAccessor accessor = OgnlRuntime
057: .getPropertyAccessor(Collection.class);
058: OgnlContextState.setGettingByKeyProperty(
059: ogContext, true);
060: return accessor.getProperty(ogContext, propVal,
061: objects[0]);
062: }
063: }
064: } catch (Exception oe) {
065: //this exception should theoretically never happen
066: //log it
067: oe.printStackTrace();
068: }
069:
070: }
071:
072: //HACK - we pass indexed method access i.e. setXXX(A,B) pattern
073: if ((objects.length == 2 && string.startsWith("set"))
074: || (objects.length == 1 && string.startsWith("get"))) {
075: Boolean exec = (Boolean) context
076: .get(DENY_INDEXED_ACCESS_EXECUTION);
077: boolean e = ((exec == null) ? false : exec.booleanValue());
078: if (!e) {
079: return super .callMethod(context, object, string,
080: objects);
081: }
082: }
083: Boolean exec = (Boolean) context.get(DENY_METHOD_EXECUTION);
084: boolean e = ((exec == null) ? false : exec.booleanValue());
085:
086: if (!e) {
087: return super .callMethod(context, object, string, objects);
088: } else {
089: return null;
090: }
091: }
092:
093: public Object callStaticMethod(Map context, Class aClass,
094: String string, Object[] objects)
095: throws MethodFailedException {
096: Boolean exec = (Boolean) context.get(DENY_METHOD_EXECUTION);
097: boolean e = ((exec == null) ? false : exec.booleanValue());
098:
099: if (!e) {
100: return super.callStaticMethod(context, aClass, string,
101: objects);
102: } else {
103: return null;
104: }
105: }
106: }
|