001: /*
002: * Copyright 2006, 2007 Odysseus Software GmbH
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package de.odysseus.el.tree.impl.ast;
017:
018: import java.lang.reflect.InvocationTargetException;
019: import java.lang.reflect.Method;
020: import java.util.List;
021:
022: import javax.el.ELContext;
023: import javax.el.ELException;
024: import javax.el.MethodInfo;
025: import javax.el.MethodNotFoundException;
026: import javax.el.PropertyNotFoundException;
027:
028: import de.odysseus.el.misc.LocalMessages;
029: import de.odysseus.el.misc.TypeConversions;
030: import de.odysseus.el.tree.Bindings;
031:
032: public final class AstMethod extends AstRightValue {
033: private final AstNode prefix;
034: private final String name;
035: private final List<AstNode> nodes;
036:
037: public AstMethod(AstNode prefix, String name, List<AstNode> nodes) {
038: this .prefix = prefix;
039: this .nodes = nodes;
040: this .name = name;
041: }
042:
043: @Override
044: public Object eval(Bindings bindings, ELContext context) {
045: Object base = prefix.eval(bindings, context);
046: if (base == null) {
047: throw new MethodNotFoundException(LocalMessages.get(
048: "error.property.base.null", prefix));
049: }
050: Object value = null;
051: try {
052: value = context.getELResolver().getValue(context, base,
053: name);
054: } catch (PropertyNotFoundException e) {
055: throw new MethodNotFoundException(LocalMessages.get(
056: "error.property.method.resolve", name, base
057: .getClass()));
058: }
059: if (!context.isPropertyResolved()) {
060: throw new MethodNotFoundException(LocalMessages.get(
061: "error.property.method.resolve", name, base
062: .getClass()));
063: }
064: Method method = null;
065: if (value instanceof Method) {
066: method = (Method) value;
067: } else if (value instanceof MethodInfo) {
068: try {
069: method = value.getClass().getMethod(name,
070: ((MethodInfo) value).getParamTypes());
071: } catch (NoSuchMethodException e) {
072: throw new MethodNotFoundException(LocalMessages.get(
073: "error.property.method.notfound", name, base
074: .getClass()), e);
075: }
076: } else {
077: throw new MethodNotFoundException(LocalMessages.get(
078: "error.property.method.notfound", name, base
079: .getClass()));
080: }
081: Class[] types = method.getParameterTypes();
082: if (nodes == null && types.length > 0 || nodes != null
083: && nodes.size() != types.length) {
084: throw new ELException(LocalMessages.get(
085: "error.property.method.invocation", name, base
086: .getClass()));
087: }
088: Object[] params = null;
089: if (types.length > 0) {
090: params = new Object[types.length];
091: for (int i = 0; i < params.length; i++) {
092: Object param = nodes.get(i).eval(bindings, context);
093: if (param != null || types[i].isPrimitive()) {
094: params[i] = TypeConversions.coerceToType(param,
095: types[i]);
096: }
097: }
098: }
099: try {
100: return method.invoke(base, params);
101: } catch (IllegalAccessException e) {
102: throw new ELException(LocalMessages.get(
103: "error.property.method.access", name, base
104: .getClass()));
105: } catch (InvocationTargetException e) {
106: throw new ELException(LocalMessages.get(
107: "error.property.method.invocation", name, base
108: .getClass()), e.getCause());
109: }
110: }
111:
112: @Override
113: public String toString() {
114: return ". " + name + "(...)";
115: }
116:
117: @Override
118: public void appendStructure(StringBuilder b, Bindings bindings) {
119: prefix.appendStructure(b, bindings);
120: b.append(".");
121: b.append(name);
122: b.append("(");
123: if (nodes != null && nodes.size() > 0) {
124: nodes.get(0).appendStructure(b, bindings);
125: for (int i = 1; i < nodes.size(); i++) {
126: b.append(", ");
127: nodes.get(i).appendStructure(b, bindings);
128: }
129: }
130: b.append(")");
131: }
132:
133: public int getCardinality() {
134: return nodes == null ? 1 : nodes.size() + 1;
135: }
136:
137: public AstNode getChild(int i) {
138: return i == 0 ? prefix : nodes == null ? null : nodes
139: .get(i - 1);
140: }
141: }
|