// --------------------------------------------------------------------------
// Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// Neither the name of the Drew Davidson nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
// --------------------------------------------------------------------------
package ognl;
import ognl.enhance.ExpressionCompiler;
import ognl.enhance.UnsupportedCompilationException;
import java.lang.reflect.Method;
/**
* @author Luke Blanshard (blanshlu@netscape.net)
* @author Drew Davidson (drew@ognl.org)
*/
public class ASTStaticMethod extends SimpleNode implements NodeType
{
private String _className;
private String _methodName;
private Class _getterClass;
public ASTStaticMethod(int id)
{
super(id);
}
public ASTStaticMethod(OgnlParser p, int id)
{
super(p, id);
}
/** Called from parser action. */
void init(String className, String methodName)
{
_className = className;
_methodName = methodName;
}
protected Object getValueBody(OgnlContext context, Object source)
throws OgnlException
{
Object[] args = OgnlRuntime.getObjectArrayPool().create(jjtGetNumChildren());
Object root = context.getRoot();
try {
for(int i = 0, icount = args.length; i < icount; ++i)
args[i] = _children[i].getValue(context, root);
return OgnlRuntime.callStaticMethod(context, _className, _methodName, args);
} finally {
OgnlRuntime.getObjectArrayPool().recycle(args);
}
}
public Class getGetterClass()
{
return _getterClass;
}
public Class getSetterClass()
{
return _getterClass;
}
public String toString()
{
String result = "@" + _className + "@" + _methodName;
result = result + "(";
if ((_children != null) && (_children.length > 0)) {
for(int i = 0; i < _children.length; i++) {
if (i > 0) {
result = result + ", ";
}
result = result + _children[i];
}
}
result = result + ")";
return result;
}
public String toGetSourceString(OgnlContext context, Object target)
{
String result = _className + "#" + _methodName + "(";
try {
Class clazz = OgnlRuntime.classForName(context, _className);
Method m = OgnlRuntime.getMethod(context, clazz, _methodName, _children, true);
if (clazz == null || m == null)
throw new UnsupportedCompilationException("Unable to find class/method combo " + _className + " / " + _methodName);
if (!context.getMemberAccess().isAccessible(context, clazz, m, _methodName))
{
throw new UnsupportedCompilationException("Method is not accessible, check your jvm runtime security settings. " +
"For static class method " + _className + " / " + _methodName);
}
if ((_children != null) && (_children.length > 0))
{
Class[] parms = m.getParameterTypes();
for(int i = 0; i < _children.length; i++)
{
if (i > 0)
{
result = result + ", ";
}
Class prevType = context.getCurrentType();
Object value = _children[i].getValue(context, context.getRoot());
String parmString = _children[i].toGetSourceString(context, context.getRoot());
if (parmString == null || parmString.trim().length() < 1)
parmString = "null";
// to undo type setting of constants when used as method parameters
if (ASTConst.class.isInstance(_children[i]))
{
context.setCurrentType(prevType);
}
parmString = ExpressionCompiler.getRootExpression(_children[i], context.getRoot(), context) + parmString;
String cast = "";
if (ExpressionCompiler.shouldCast(_children[i]))
{
cast = (String)context.remove(ExpressionCompiler.PRE_CAST);
}
if (cast == null)
cast = "";
if (!ASTConst.class.isInstance(_children[i]))
parmString = cast + parmString;
Class valueClass = value != null ? value.getClass() : null;
if (NodeType.class.isAssignableFrom(_children[i].getClass()))
valueClass = ((NodeType)_children[i]).getGetterClass();
if (valueClass != parms[i])
{
if (parms[i].isArray())
{
parmString = OgnlRuntime.getCompiler()
.createLocalReference(context,
"(" + ExpressionCompiler.getCastString(parms[i])
+ ")ognl.OgnlOps.toArray(" + parmString + ", " + parms[i].getComponentType().getName()
+ ".class, true)",
parms[i]
);
} else if (parms[i].isPrimitive())
{
Class wrapClass = OgnlRuntime.getPrimitiveWrapperClass(parms[i]);
parmString = OgnlRuntime.getCompiler().createLocalReference(context,
"((" + wrapClass.getName()
+ ")ognl.OgnlOps.convertValue(" + parmString + ","
+ wrapClass.getName() + ".class, true))."
+ OgnlRuntime.getNumericValueGetter(wrapClass),
parms[i]
);
} else if (parms[i] != Object.class)
{
parmString = OgnlRuntime.getCompiler()
.createLocalReference(context,
"(" + parms[i].getName() + ")ognl.OgnlOps.convertValue(" + parmString + "," + parms[i].getName() + ".class)",
parms[i]
);
} else if ((NodeType.class.isInstance(_children[i])
&& ((NodeType)_children[i]).getGetterClass() != null
&& Number.class.isAssignableFrom(((NodeType)_children[i]).getGetterClass()))
|| valueClass.isPrimitive())
{
parmString = " ($w) " + parmString;
} else if (valueClass.isPrimitive())
{
parmString = "($w) " + parmString;
}
}
result += parmString;
}
}
result += ")";
try
{
Object contextObj = getValueBody(context, target);
context.setCurrentObject(contextObj);
} catch (Throwable t)
{
// ignore
}
if (m != null)
{
_getterClass = m.getReturnType();
context.setCurrentType(m.getReturnType());
context.setCurrentAccessor(OgnlRuntime.getCompiler().getSuperOrInterfaceClass(m, m.getDeclaringClass()));
}
} catch (Throwable t)
{
throw OgnlOps.castToRuntime(t);
}
return result;
}
public String toSetSourceString(OgnlContext context, Object target)
{
return toGetSourceString(context, target);
}
}