예제 #1
0
        /// <summary>
        /// Renders the input reader using the context into the output writer.
        /// To be used when a template is dynamically constructed, or want to
        /// use Velocity as a token replacer.
        /// </summary>
        /// <param name="context">context to use in rendering input string</param>
        /// <param name="out"> Writer in which to render the output</param>
        /// <param name="logTag"> string to be used as the template name for log messages in case of error</param>
        /// <param name="reader">Reader containing the VTL to be rendered</param>
        /// <returns>true if successful, false otherwise.  If false, see Velocity runtime log</returns>
        public static bool Evaluate(IContext context, TextWriter writer, String logTag, TextReader reader)
        {
            SimpleNode nodeTree = null;

            try
            {
                nodeTree = RuntimeSingleton.parse(reader, logTag);
            }
            catch (ParseException pex)
            {
                throw new ParseErrorException(pex.Message);
            }

            /*
             * now we want to init and render
             */

            if (nodeTree != null)
            {
                InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context);

                ica.PushCurrentTemplateName(logTag);

                try
                {
                    try
                    {
                        nodeTree.init(ica, RuntimeSingleton.RuntimeServices);
                    }
                    catch (Exception e)
                    {
                        RuntimeSingleton.error("Velocity.evaluate() : init exception for tag = " + logTag + " : " + e);
                    }

                    /*
                     *  now render, and let any exceptions fly
                     */

                    nodeTree.render(ica, writer);
                }
                finally
                {
                    ica.PopCurrentTemplateName();
                }

                return(true);
            }

            return(false);
        }
예제 #2
0
        internal bool Render(DvslNode node, IContext context, TextWriter writer)
        {
            /*
             *  find if we have an AST where the xpath expression mathes
             *  for this node
             */

            XmlNode        dom4jnode = (XmlNode)node.NodeImpl;
            XPathNavigator nav       = dom4jnode.CreateNavigator();
            SimpleNode     sn        = null;

            for (int i = 0; i < xpathList.Count; i++)
            {
                Hashtable m = (Hashtable)xpathList[i];

                XPathExpression expr = nav.Compile((String)m["xpath"]);

                if (nav.Matches((String)m["xpath"]))
                {
                    sn = (SimpleNode)m["ast"];
                    break;
                }
            }

            // if we found something, render
            if (sn != null)
            {
                InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context);
                ica.PushCurrentTemplateName(node.Name);

                try
                {
                    sn.render(ica, writer);
                }
                finally
                {
                    ica.PopCurrentTemplateName();
                }

                return(true);
            }

            return(false);
        }
        /// <summary> Return name of this Velocimacro.
        /// </summary>
        /// <summary> Velocimacros are always LINE
        /// type directives.
        /// </summary>
        /// <summary>   sets the directive name of this VM
        /// </summary>
        /// <summary>  sets the array of arguments specified in the macro definition
        /// </summary>
        /// <summary>  returns the number of ars needed for this VM
        /// </summary>
        /// <summary>   Sets the orignal macro body.  This is simply the cat of the macroArray, but the
        /// Macro object creates this once during parsing, and everyone shares it.
        /// Note : it must not be modified.
        /// </summary>
        /// <summary>   Renders the macro using the context
        /// </summary>
        public override bool render(InternalContextAdapter context, TextWriter writer, INode node)
        {
            try
            {
                /*
                 *  it's possible the tree hasn't been parsed yet, so get
                 *  the VMManager to parse and init it
                 */

                if (nodeTree != null)
                {
                    if (!init_Renamed_Field)
                    {
                        nodeTree.init(context, rsvc);
                        init_Renamed_Field = true;
                    }

                    /*
                     *  wrap the current context and add the VMProxyArg objects
                     */

                    VMContext vmc = new VMContext(context, rsvc);

                    for (int i = 1; i < argArray.Length; i++)
                    {
                        /*
                         *  we can do this as VMProxyArgs don't change state. They change
                         *  the context.
                         */

                        VMProxyArg arg = (VMProxyArg)proxyArgHash[argArray[i]];
                        vmc.AddVMProxyArg(arg);
                    }

                    /*
                     *  now render the VM
                     */

                    nodeTree.render(vmc, writer);
                }
                else
                {
                    rsvc.error("VM error : " + macroName + ". Null AST");
                }
            }
            catch (Exception e)
            {
                /*
                 *  if it's a MIE, it came from the render.... throw it...
                 */

                if (e is MethodInvocationException)
                {
                    throw (MethodInvocationException)e;
                }

                rsvc.error("VelocimacroProxy.render() : exception VM = #" + macroName + "() : " + StringUtils.stackTrace(e));
            }

            return(true);
        }
예제 #4
0
        /// <summary>  returns the value of the reference.  Generally, this is only
        /// called for dynamic proxies, as the static ones should have
        /// been stored in the VMContext's localcontext store
        /// *
        /// </summary>
        /// <param name="context">Context to use for getting current value
        /// </param>
        /// <returns>Object value
        /// *
        ///
        /// </returns>
        public Object getObject(InternalContextAdapter context)
        {
            try
            {
                /*
                 *  we need to output based on our type
                 */

                Object retObject = null;

                if (type == ParserTreeConstants.JJTREFERENCE)
                {
                    /*
                     *  two cases :  scalar reference ($foo) or multi-level ($foo.bar....)
                     */

                    if (numTreeChildren == 0)
                    {
                        /*
                         *  if I am a single-level reference, can I not get get it out of my context?
                         */

                        retObject = context.Get(singleLevelRef);
                    }
                    else
                    {
                        /*
                         *  I need to let the AST produce it for me.
                         */

                        retObject = nodeTree.execute(null, context);
                    }
                }
                else if (type == ParserTreeConstants.JJTOBJECTARRAY)
                {
                    retObject = nodeTree.Value(context);
                }
                else if (type == ParserTreeConstants.JJTINTEGERRANGE)
                {
                    retObject = nodeTree.Value(context);
                }
                else if (type == ParserTreeConstants.JJTTRUE)
                {
                    retObject = staticObject;
                }
                else if (type == ParserTreeConstants.JJTFALSE)
                {
                    retObject = staticObject;
                }
                else if (type == ParserTreeConstants.JJTSTRINGLITERAL)
                {
                    retObject = nodeTree.Value(context);
                }
                else if (type == ParserTreeConstants.JJTNUMBERLITERAL)
                {
                    retObject = staticObject;
                }
                else if (type == ParserTreeConstants.JJTTEXT)
                {
                    /*
                     *  this really shouldn't happen.  text is just a thowaway arg for #foreach()
                     */

                    try
                    {
                        StringWriter writer = new StringWriter();
                        nodeTree.render(context, writer);

                        retObject = writer;
                    }
                    catch (Exception e)
                    {
                        rsvc.error("VMProxyArg.getObject() : error rendering reference : " + e);
                    }
                }
                else if (type == GENERALSTATIC)
                {
                    retObject = staticObject;
                }
                else
                {
                    rsvc.error("Unsupported VM arg type : VM arg = " + callerReference + " type = " + type + "( VMProxyArg.getObject() )");
                }

                return(retObject);
            }
            catch (MethodInvocationException mie)
            {
                /*
                 *  not ideal, but otherwise we propogate out to the
                 *  VMContext, and the Context interface's put/get
                 *  don't throw. So this is a the best compromise
                 *  I can think of
                 */

                rsvc.error("VMProxyArg.getObject() : method invocation error getting value : " + mie);

                return(null);
            }
        }