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 javax.el.MethodInfo;
037: import javax.el.PropertyNotFoundException;
038: import java.io.IOException;
039: import java.lang.reflect.InvocationTargetException;
040: import java.lang.reflect.Method;
041:
042: /**
043: * Represents an array reference:
044: *
045: * <pre>
046: * a[b]
047: * </pre>
048: */
049: public class ArrayResolverExpr extends Expr {
050: private Expr _left;
051: private Expr _right;
052:
053: // cached getter method
054: private transient Class _lastClass;
055: private transient String _lastField;
056: private transient Method _lastMethod;
057:
058: /**
059: * Creates a new array expression.
060: *
061: * @param left the object expression
062: * @param right the index expression.
063: */
064: public ArrayResolverExpr(Expr left, Expr right) {
065: _left = left;
066: _right = right;
067: }
068:
069: /**
070: * Returns the base expression.
071: */
072: public Expr getExpr() {
073: return _left;
074: }
075:
076: /**
077: * Returns the index expression.
078: */
079: public Expr getIndex() {
080: return _right;
081: }
082:
083: /**
084: * Creates a method for constant arrays.
085: */
086: @Override
087: public Expr createMethod(Expr[] args) {
088: if (!(_right instanceof StringLiteral))
089: return null;
090:
091: StringLiteral literal = (StringLiteral) _right;
092:
093: return new MethodExpr(_left, literal.getValue(), args);
094: }
095:
096: /**
097: * Evaluates the expression as applicable to the provided context, and returns
098: * the most general type that can be accepted by the setValue(javax.el.ELContext,
099: * java.lang.Object) method.
100: *
101: * @param env
102: * @return
103: * @throws PropertyNotFoundException
104: * @throws ELException
105: */
106: @Override
107: public Class<?> getType(ELContext env)
108: throws PropertyNotFoundException, ELException {
109: Object aObj = _left.getValue(env);
110:
111: if (aObj == null)
112: return null;
113:
114: Object fieldObj = _right.getValue(env);
115:
116: if (fieldObj == null)
117: return null;
118:
119: return env.getELResolver().getType(env, aObj, fieldObj);
120: }
121:
122: /**
123: * Evaluate the expression as an object.
124: *
125: * @param env the variable environment
126: *
127: * @return the evaluated object
128: */
129: @Override
130: public Object getValue(ELContext env) throws ELException {
131: Object aObj = _left.getValue(env);
132:
133: if (aObj == null)
134: return null;
135:
136: Object fieldObj = _right.getValue(env);
137: if (fieldObj == null)
138: return null;
139:
140: return env.getELResolver().getValue(env, aObj, fieldObj);
141: }
142:
143: /**
144: * Returns the read-only value of the expression.
145: *
146: * @param env the variable environment
147: *
148: * @return true if read-only
149: */
150: @Override
151: public boolean isReadOnly(ELContext env) throws ELException {
152: Object aObj = _left.getValue(env);
153:
154: if (aObj == null)
155: return true;
156:
157: Object fieldObj = _right.getValue(env);
158: if (fieldObj == null)
159: return true;
160:
161: return env.getELResolver().isReadOnly(env, aObj, fieldObj);
162: }
163:
164: /**
165: * Evaluate the expression as an object.
166: *
167: * @param env the variable environment
168: *
169: * @return the evaluated object
170: */
171: @Override
172: public void setValue(ELContext env, Object value)
173: throws ELException {
174: Object aObj = _left.getValue(env);
175:
176: if (aObj == null)
177: throw new PropertyNotFoundException(L.l(
178: "'{0}' is null in '{1}'", _left.toString(),
179: toString()));
180:
181: Object fieldObj = _right.getValue(env);
182: if (fieldObj == null)
183: throw new PropertyNotFoundException(L.l(
184: "'{0}' is null in '{1}'", _right.toString(),
185: toString()));
186:
187: env.getELResolver().setValue(env, aObj, fieldObj, value);
188: }
189:
190: /**
191: * Evaluates the expression, returning an object.
192: *
193: * @param env the variable environment
194: *
195: * @return the value of the expression as an object
196: */
197: @Override
198: public MethodInfo getMethodInfo(ELContext env, Class<?> returnType,
199: Class<?>[] argTypes) throws ELException {
200: Object base = _left.getValue(env);
201:
202: if (base == null)
203: throw new ELException(L.l(
204: "'{0}' is an illegal method expression.",
205: toString()));
206:
207: String name = _right.evalString(env);
208:
209: try {
210: Method method = base.getClass().getMethod(name, argTypes);
211:
212: return new MethodInfo(_right.evalString(env), method
213: .getReturnType(), argTypes);
214: } catch (NoSuchMethodException e) {
215: throw new javax.el.MethodNotFoundException(e);
216: }
217: }
218:
219: /**
220: * Evaluates the expression, returning an object.
221: *
222: * @param env the variable environment
223: *
224: * @return the value of the expression as an object
225: */
226: @Override
227: public Object invoke(ELContext env, Class<?>[] argTypes,
228: Object[] args) throws ELException {
229: Object base = _left.getValue(env);
230:
231: if (base == null)
232: throw new javax.el.MethodNotFoundException(L.l(
233: "'{0}' is an illegal method expression.",
234: toString()));
235:
236: String name = _right.evalString(env);
237:
238: try {
239: Method method = base.getClass().getMethod(name, argTypes);
240:
241: return method.invoke(base, args);
242: } catch (NoSuchMethodException e) {
243: throw new javax.el.MethodNotFoundException(e);
244: } catch (IllegalAccessException e) {
245: throw new ELException(e);
246: } catch (InvocationTargetException e) {
247: throw new ELException(e.getCause());
248: }
249: }
250:
251: /**
252: * Prints the code to create an LongLiteral.
253: *
254: * @param os stream to the generated *.java code
255: */
256: @Override
257: public void printCreate(WriteStream os) throws IOException {
258: os.print("new com.caucho.el.ArrayResolverExpr(");
259: _left.printCreate(os);
260: os.print(", ");
261: _right.printCreate(os);
262: os.print(")");
263: }
264:
265: /**
266: * Returns true for equal strings.
267: */
268: public boolean equals(Object o) {
269: if (!(o instanceof ArrayResolverExpr))
270: return false;
271:
272: ArrayResolverExpr expr = (ArrayResolverExpr) o;
273:
274: return (_left.equals(expr._left) && _right.equals(expr._right));
275: }
276:
277: /**
278: * Returns a readable representation of the expr.
279: */
280: public String toString() {
281: return _left + "[" + _right + "]";
282: }
283: }
|