001: package org.gui4j.core.call;
002:
003: import java.lang.reflect.InvocationTargetException;
004: import java.lang.reflect.Modifier;
005: import java.util.ArrayList;
006: import java.util.Arrays;
007: import java.util.List;
008: import java.util.Map;
009:
010: import org.apache.commons.logging.Log;
011: import org.apache.commons.logging.LogFactory;
012:
013: import org.gui4j.core.Gui4jReflectionManager;
014: import org.gui4j.core.util.FieldCall;
015: import org.gui4j.core.util.FieldCallReflection;
016: import org.gui4j.core.util.MethodCall;
017: import org.gui4j.exception.Gui4jUncheckedException;
018:
019: final class Gui4jAccessMethod extends Gui4jAccessImpl {
020: static final Log mLogger = LogFactory
021: .getLog(Gui4jAccessMethod.class);
022:
023: private final Gui4jAccessImpl[] mParameter;
024: private MethodCall mMethod;
025: private FieldCall mField;
026: private final Gui4jAccessImpl mThisAccess;
027: private final boolean mLogInvoke;
028:
029: Gui4jAccessMethod(ParseCtx parseCtx, Gui4jAccessImpl this Access,
030: String accessPath) {
031: mThisAccess = this Access;
032: mLogInvoke = parseCtx.getGui4jComponentContainer().getGui4j()
033: .logInvoke();
034: int len = accessPath.length();
035: int startIndex = parseCtx.i;
036: int lParenIndex = accessPath.indexOf('(', startIndex);
037: int endIndex = minIndex(accessPath, ".,;)}", startIndex);
038: if (endIndex == -1) {
039: endIndex = accessPath.length();
040: }
041:
042: Gui4jAccessImpl[] parameter = new Gui4jAccessImpl[0];
043: boolean parenthesisUsed;
044: String methodName;
045: if (lParenIndex != -1 && lParenIndex < endIndex) {
046: // parameters are provided
047: parenthesisUsed = true;
048: methodName = accessPath.substring(startIndex, lParenIndex);
049: parseCtx.i = lParenIndex + 1;
050: List parameterList = new ArrayList();
051: while (true) {
052: Gui4jCallParser.skipSpaces(parseCtx, len);
053: if (parseCtx.i >= len) {
054: Object[] args = { accessPath,
055: new Integer(parseCtx.i) };
056: throw new Gui4jUncheckedException.ResourceError(
057: parseCtx.getConfigurationName(), parseCtx
058: .getLineNumber(),
059: RESOURCE_ERROR_access_unexpected_character,
060: args);
061: }
062: if (accessPath.charAt(parseCtx.i) == ',') {
063: parseCtx.i = parseCtx.i + 1;
064: continue;
065: }
066:
067: if (accessPath.charAt(parseCtx.i) == ')') {
068: parseCtx.i = parseCtx.i + 1;
069: parameter = new Gui4jAccessImpl[parameterList
070: .size()];
071: for (int i = 0; i < parameter.length; i++) {
072: parameter[i] = (Gui4jAccessImpl) parameterList
073: .get(i);
074: }
075: break;
076: }
077:
078: // Parameter expected
079: Gui4jAccessImpl gui4jAccess = parseCtx
080: .getGui4jCallParser().parseCallSequence(
081: parseCtx, accessPath);
082: /*
083: getInstance(
084: parseCtx,
085: parseCtx.getBaseAccess(),
086: accessPath);
087: */
088: parameterList.add(gui4jAccess);
089: }
090: } else {
091: // no parameters
092: parenthesisUsed = false;
093: methodName = accessPath.substring(startIndex, endIndex);
094: parseCtx.i = endIndex;
095: }
096:
097: // lookup method
098: mParameter = parameter;
099: if (!parenthesisUsed) {
100: // try to access field
101: try {
102: mField = FieldCallReflection.getField(this Access
103: .getResultClass(), methodName);
104: } catch (NoSuchFieldException e) {
105: // simply ignore, because we ar trying to find a corresponding method
106: }
107: }
108: if (mField == null) {
109: Class[] arguments = new Class[parameter.length];
110: for (int i = 0; i < parameter.length; i++) {
111: arguments[i] = parameter[i].getResultClass();
112: }
113: String context = parseCtx.getConfigurationName();
114: {
115: int lineNumber = parseCtx.getLineNumber();
116: if (lineNumber != -1) {
117: context = context + "(:" + lineNumber + ")";
118: }
119: }
120: mMethod = parseCtx.getGui4jReflectionManager().getMethod(
121: context, this Access.getResultClass(), methodName,
122: arguments);
123: } else {
124: mMethod = null;
125: }
126: }
127:
128: public Class getResultClass() {
129: if (mField != null) {
130: return mField.getType();
131: } else {
132: return mMethod.getReturnType();
133: }
134: }
135:
136: public boolean isConstant() {
137: return false;
138: }
139:
140: public Object getValue(Object baseInstance, Object orgThisInstance,
141: Map paramMap) {
142: Object this Instance = mThisAccess.getValue(baseInstance,
143: orgThisInstance, paramMap);
144: if (mField != null) {
145: try {
146: Object result = mField.get(this Instance);
147: return result;
148: } catch (IllegalAccessException e) {
149: throw new Gui4jUncheckedException.ProgrammingError(
150: PROGRAMMING_ERROR_illegal_access_exception, e);
151: }
152: } else {
153: Object[] argumentValue = mParameter.length == 0 ? null
154: : new Object[mParameter.length];
155: for (int i = 0; i < mParameter.length; i++) {
156: argumentValue[i] = mParameter[i].getValue(baseInstance,
157: this Instance, paramMap);
158: }
159: try {
160: if (mLogInvoke) {
161: List l = new ArrayList();
162: if (argumentValue != null) {
163: l.addAll(Arrays.asList(argumentValue));
164: }
165: mLogger.debug("Invoking: " + mMethod
166: + ", thisInstance = " + this Instance
167: + ", arguments=" + l);
168: }
169: boolean ok = this Instance != null
170: || ((mMethod.getModifiers() & Modifier.STATIC) != 0);
171: if (!ok) {
172: List l = new ArrayList();
173: if (argumentValue != null) {
174: l.addAll(Arrays.asList(argumentValue));
175: }
176: mLogger.warn("Invoking non-static method "
177: + mMethod
178: + " with null instance and arguments " + l);
179: }
180: assert ok;
181: Object result = null;
182: try {
183: result = mMethod
184: .invoke(this Instance, argumentValue);
185: } catch (IllegalArgumentException e) {
186: List l = new ArrayList();
187: if (argumentValue != null) {
188: l.addAll(Arrays.asList(argumentValue));
189: }
190: mLogger.debug("Invocation: " + mMethod
191: + ", thisInstance = " + this Instance
192: + ", arguments=" + l + " failed");
193: throw e;
194: }
195: if (mLogInvoke) {
196: List l = new ArrayList();
197: if (argumentValue != null) {
198: l.addAll(Arrays.asList(argumentValue));
199: }
200: mLogger.debug("Result of Invocation: " + mMethod
201: + ", thisInstance = " + this Instance
202: + ", arguments=" + l + ", result = "
203: + result);
204: }
205: return result;
206: } catch (IllegalAccessException e) {
207: mLogger.warn(e.getMessage() + mMethod);
208: throw new Gui4jUncheckedException.ProgrammingError(
209: PROGRAMMING_ERROR_illegal_access_exception, e);
210: } catch (InvocationTargetException e) {
211: // mLogger.warn(e.getTargetException().getMessage() + mMethod, e.getTargetException());
212: Gui4jReflectionManager
213: .handleInvocationTargetException(e);
214: throw new Gui4jUncheckedException.ProgrammingError(
215: PROGRAMMING_ERROR_invocation_target_exception,
216: e);
217: }
218: }
219: }
220:
221: /**
222: * @see java.lang.Object#toString()
223: */
224: public String toString() {
225: return mMethod.toString();
226: }
227:
228: }
|