001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.el;
031:
032: import com.caucho.vfs.WriteStream;
033:
034: import javax.el.ELContext;
035: import javax.el.ELException;
036: import java.io.IOException;
037: import java.lang.reflect.Method;
038: import java.lang.reflect.Modifier;
039:
040: /**
041: * Represents a named method call on an object.
042: */
043: public class MethodExpr extends Expr {
044: private Expr _expr;
045: private String _methodName;
046:
047: private Expr[] _args;
048:
049: /**
050: * Creates a new method expression.
051: *
052: * @param expr the expression generating the object on which the method
053: * is to be called
054: * @param methodName the name of the method to call
055: * @param args the arguments for the method
056: */
057: public MethodExpr(Expr expr, String methodName, Expr[] args) {
058: _expr = expr;
059: _methodName = methodName;
060: _args = args;
061: }
062:
063: /**
064: * Evaluate the expression as an object.
065: *
066: * @param env the variable environment
067: */
068: @Override
069: public Object getValue(ELContext env) throws ELException {
070: Object aObj = _expr.getValue(env);
071:
072: if (aObj == null)
073: return null;
074:
075: Object[] objs = new Object[_args.length];
076:
077: try {
078: Method method = findMethod(aObj.getClass());
079:
080: if (method != null) {
081: Class[] params = method.getParameterTypes();
082:
083: for (int j = 0; j < params.length; j++) {
084: objs[j] = evalArg(params[j], _args[j], env);
085: }
086:
087: // XXX: probably should look for the interface instead.
088: try {
089: method.setAccessible(true);
090: } catch (Throwable e) {
091: }
092:
093: return method.invoke(aObj, objs);
094: }
095:
096: return null;
097: } catch (Exception e) {
098: return invocationError(e);
099: }
100: }
101:
102: private Method findMethod(Class type) {
103: if (type == null)
104: return null;
105:
106: if (Modifier.isPublic(type.getModifiers())) {
107: Method[] methods = type.getDeclaredMethods();
108:
109: for (int i = 0; i < methods.length; i++) {
110: Method method = methods[i];
111:
112: if (!Modifier.isPublic(method.getModifiers()))
113: continue;
114:
115: Class[] params = method.getParameterTypes();
116:
117: if (method.getName().equals(_methodName)
118: && params.length == _args.length)
119: return method;
120: }
121: }
122:
123: Class[] interfaces = type.getInterfaces();
124: for (int i = 0; i < interfaces.length; i++) {
125: Method method = findMethod(interfaces[i]);
126: if (method != null)
127: return method;
128: }
129:
130: return findMethod(type.getSuperclass());
131: }
132:
133: static Object evalArg(Class cl, Expr expr, ELContext env)
134: throws ELException {
135: Marshall marshall = Marshall.create(cl);
136:
137: return marshall.marshall(expr, env);
138: }
139:
140: /**
141: * Prints the code to create an LongLiteral.
142: */
143: @Override
144: public void printCreate(WriteStream os) throws IOException {
145: os.print("new com.caucho.el.MethodExpr(");
146: _expr.printCreate(os);
147: os.print(", \"");
148: os.print(_methodName);
149: os.print("\", new com.caucho.el.Expr[] {");
150:
151: for (int i = 0; i < _args.length; i++) {
152: if (i != 0)
153: os.print(", ");
154: _args[i].printCreate(os);
155: }
156: os.println("})");
157: }
158:
159: /**
160: * Returns true for equal strings.
161: */
162: public boolean equals(Object o) {
163: if (!(o instanceof MethodExpr))
164: return false;
165:
166: MethodExpr expr = (MethodExpr) o;
167:
168: if (!_expr.equals(expr._expr))
169: return false;
170:
171: if (!_methodName.equals(expr._methodName))
172: return false;
173:
174: if (_args.length != expr._args.length)
175: return false;
176:
177: for (int i = 0; i < _args.length; i++) {
178: if (!_args[i].equals(expr._args[i]))
179: return false;
180: }
181:
182: return true;
183: }
184:
185: /**
186: * Returns the printed version.
187: */
188: public String toString() {
189: return "MethodExpr[" + _expr + "," + _methodName + "]";
190: }
191: }
|