public Object execute()

in velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMethod.java [143:263]


    public Object execute(Object o, InternalContextAdapter context)
        throws MethodInvocationException
    {
        try
        {
            rsvc.getLogContext().pushLogContext(this, uberInfo);

            /*
             *  new strategy (strategery!) for introspection. Since we want
             *  to be thread- as well as context-safe, we *must* do it now,
             *  at execution time.  There can be no in-node caching,
             *  but if we are careful, we can do it in the context.
             */
            Object [] params = new Object[paramCount];

              /*
               * sadly, we do need recalc the values of the args, as this can
               * change from visit to visit
               */
            final Class<?>[] paramClasses =
                paramCount > 0 ? new Class[paramCount] : EMPTY_CLASS_ARRAY;

            for (int j = 0; j < paramCount; j++)
            {
                params[j] = jjtGetChild(j + 1).value(context);
                if (params[j] != null)
                {
                    paramClasses[j] = params[j].getClass();
                }
            }

            VelMethod method = ClassUtils.getMethod(methodName, params, paramClasses,
                o, context, this, strictRef);

            // warn if method wasn't found (if strictRef is true, then ClassUtils did throw an exception)
            if (o != null && method == null && logOnInvalid)
            {
                StringBuilder plist = new StringBuilder();
                for (int i = 0; i < params.length; i++)
                {
                    Class<?> param = paramClasses[i];
                    plist.append(param == null ? "null" : param.getName());
                    if (i < params.length - 1)
                        plist.append(", ");
                }
                log.debug("Object '{}' does not contain method {}({}) (or several ambiguous methods) at {}[line {}, column {}]", o.getClass().getName(), methodName, plist, getTemplateName(), getLine(), getColumn());
            }

            /*
             * The parent class (typically ASTReference) uses the icache entry
             * under 'this' key to distinguish a valid null result from a non-existent method.
             * So update this dummy cache value if necessary.
             */
            IntrospectionCacheData prevICD = context.icacheGet(this);
            if (method == null)
            {
                if (prevICD != null)
                {
                    context.icachePut(this, null);
                }
                return null;
            }
            else if (prevICD == null)
            {
                context.icachePut(this, new IntrospectionCacheData()); // no need to fill in its members
            }

            try
            {
                /*
                 *  get the returned object.  It may be null, and that is
                 *  valid for something declared with a void return type.
                 *  Since the caller is expecting something to be returned,
                 *  as long as things are peachy, we can return an empty
                 *  String so ASTReference() correctly figures out that
                 *  all is well.
                 */

                Object obj = method.invoke(o, params);

                if (obj == null)
                {
                    if( method.getReturnType() == Void.TYPE)
                    {
                        return "";
                    }
                }

                return obj;
            }
            catch( InvocationTargetException ite )
            {
                return handleInvocationException(o, context, ite.getTargetException());
            }

            /* Can also be thrown by method invocation */
            catch( IllegalArgumentException t )
            {
                return handleInvocationException(o, context, t);
            }

            /*
             * pass through application level runtime exceptions
             */
            catch( RuntimeException e )
            {
                throw e;
            }
            catch( Exception e )
            {
                String msg = "ASTMethod.execute() : exception invoking method '"
                             + methodName + "' in " + o.getClass();
                log.error(msg, e);
                throw new VelocityException(msg, e, rsvc.getLogContext().getStackTrace());
            }
        }
        finally
        {
            rsvc.getLogContext().popLogContext();
        }
    }