/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.el; import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import javax.el.ELContext; import javax.el.ELException; import com.caucho.config.types.Signature; import com.caucho.vfs.WriteStream; /** * Represents a method call. The expr will evaluate to a method. */ public class StaticMethodExpr extends Expr { private static final Object []NULL_ARGS = new Object[0]; private Method _method; private Marshall []_marshall; private boolean _isVoid; /** * Creates a new method expression. * * @param method - the target method */ public StaticMethodExpr(Method method) { _method = method; initMethod(); } /** * Creates a new static method. * * @param signature signature */ public StaticMethodExpr(String signature) { try { Signature sig = new Signature(); sig.addText(signature); sig.init(); _method = sig.getMethod(); if (_method == null) throw new RuntimeException(L.l("'{0}' is an unknown method", sig)); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); // log.log(Level.FINE, e.toString(), e); } initMethod(); } /** * Initialize the marshall arguments. */ private void initMethod() { Class []param = _method.getParameterTypes(); _marshall = new Marshall[param.length]; for (int i = 0; i < _marshall.length; i++) { _marshall[i] = Marshall.create(param[i]); } _isVoid = void.class.equals(_method.getReturnType()); } /** * Evaluate the expression as an object. * * @param env the variable environment */ @Override public Object getValue(ELContext env) throws ELException { return _method; } /** * Evaluate the expression as an object. * * @param env the variable environment */ public Object evalMethod(Expr []args, ELContext env) throws ELException { if (_marshall.length != args.length) { // jsp/18i8 throw new ELParseException(L.l("Arguments to '{0}' do not match expected length {1}.", _method.getName(), _marshall.length)); } try { Object []objs; if (args.length > 0) { objs = new Object[args.length]; for (int i = 0; i < _marshall.length; i++) objs[i] = _marshall[i].marshall(args[i], env); } else objs = NULL_ARGS; if (! _isVoid) return _method.invoke(null, objs); else { _method.invoke(null, objs); return null; } } catch (ELException e) { throw e; } catch (InvocationTargetException e) { throw new ELException(e.getCause()); } catch (Exception e) { throw new ELException(e); } } /** * Prints the code to create an LongLiteral. */ public void printCreate(WriteStream os) throws IOException { os.print("new com.caucho.el.StaticMethodExpr(\""); printType(os, _method.getReturnType()); os.print(" "); os.print(_method.getDeclaringClass().getName()); os.print("."); os.print(_method.getName()); os.print("("); Class<?> []parameterTypes = _method.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { if (i != 0) os.print(", "); printType(os, parameterTypes[i]); } os.print(")"); os.print("\")"); } private void printType(WriteStream os, Class<?> cl) throws IOException { if (cl.isArray()) { printType(os, cl.getComponentType()); os.print("[]"); } else os.print(cl.getName()); } private Object writeReplace() { StringBuilder sig = new StringBuilder(); addType(sig, _method.getReturnType()); sig.append(" "); sig.append(_method.getDeclaringClass().getName()); sig.append("."); sig.append(_method.getName()); sig.append("("); Class<?> []param = _method.getParameterTypes(); for (int i = 0; i < param.length; i++) { if (i != 0) sig.append(","); addType(sig, param[i]); } sig.append(")"); return new Handle(sig.toString()); } private void addType(StringBuilder sb, Class<?> cl) { if (cl.isArray()) { addType(sb, cl.getComponentType()); sb.append("[]"); } else sb.append(cl.getName()); } /** * Returns true for equal strings. */ public boolean equals(Object o) { if (! (o instanceof StaticMethodExpr)) return false; StaticMethodExpr expr = (StaticMethodExpr) o; return _method.equals(expr._method); } public String toString() { return _method.getName(); } static class Handle implements Serializable { private String _signature; private Handle() { } private Handle(String signature) { _signature = signature; } public Object readResolve() { return new StaticMethodExpr(_signature); } } }