public bool Evaluate(IContext context, TextWriter writer, string logTag, TextReader reader) { SimpleNode simpleNode = null; try { simpleNode = this.ri.Parse(reader, logTag); } catch (ParseException ex) { throw new ParseErrorException(ex.Message, ex); } bool result; if (simpleNode != null) { InternalContextAdapterImpl internalContextAdapterImpl = new InternalContextAdapterImpl(context); internalContextAdapterImpl.PushCurrentTemplateName(logTag); try { try { simpleNode.Init(internalContextAdapterImpl, this.ri); } catch (System.Exception ex2) { this.ri.Error(string.Concat(new object[] { "Velocity.evaluate() : init exception for tag = ", logTag, " : ", ex2 })); } simpleNode.Render(internalContextAdapterImpl, writer); } finally { internalContextAdapterImpl.PopCurrentTemplateName(); } result = true; } else { result = false; } return(result); }
/// <summary> /// Renders the macro using the context /// </summary> public override bool Render(IInternalContextAdapter 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) { runtimeServices.Error(string.Format("VM error : {0}. Null AST", macroName)); } else { if (!init) { nodeTree.Init(context, runtimeServices); init = true; } // wrap the current context and add the VMProxyArg objects VMContext vmContext = new VMContext(context, runtimeServices); 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]]; vmContext.AddVMProxyArg(arg); } // now render the VM nodeTree.Render(vmContext, writer); } } catch (Exception e) { // if it's a MIE, it came from the render.... throw it... if (e is MethodInvocationException) { throw; } runtimeServices.Error(string.Format("VelocimacroProxy.render() : exception VM = #{0}() : {1}", macroName, e)); } return(true); }
/// <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="writer"> 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 parseException) { throw new ParseErrorException(parseException.Message, parseException); } // now we want to init and render if (nodeTree != null) { InternalContextAdapterImpl internalContextAdapterImpl = new InternalContextAdapterImpl(context); internalContextAdapterImpl.PushCurrentTemplateName(logTag); try { try { nodeTree.Init(internalContextAdapterImpl, RuntimeSingleton.RuntimeServices); } catch (Exception exception) { RuntimeSingleton.Error( string.Format("Velocity.evaluate() : init exception for tag = {0} : {1}", logTag, exception)); } // now render, and let any exceptions fly nodeTree.Render(internalContextAdapterImpl, writer); } finally { internalContextAdapterImpl.PopCurrentTemplateName(); } return(true); } return(false); }
/// <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(IInternalContextAdapter context) { try { /* * we need to output based on our type */ Object retObject = null; if (type == ParserTreeConstants.REFERENCE) { /* * 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.OBJECT_ARRAY) { retObject = nodeTree.Value(context); } else if (type == ParserTreeConstants.INTEGER_RANGE) { retObject = nodeTree.Value(context); } else if (type == ParserTreeConstants.TRUE) { retObject = staticObject; } else if (type == ParserTreeConstants.FALSE) { retObject = staticObject; } else if (type == ParserTreeConstants.STRING_LITERAL) { retObject = nodeTree.Value(context); } else if (type == ParserTreeConstants.NUMBER_LITERAL) { retObject = staticObject; } else if (type == ParserTreeConstants.TEXT) { /* * this really shouldn't happen. text is just a throwaway arg for #foreach() */ try { StringWriter writer = new StringWriter(); nodeTree.Render(context, writer); retObject = writer; } catch (System.Exception e) { runtimeServices.Error(string.Format("VMProxyArg.getObject() : error rendering reference : {0}", e)); } } else if (type == GENERALSTATIC) { retObject = staticObject; } else { runtimeServices.Error( string.Format("Unsupported VM arg type : VM arg = {0} type = {1}( VMProxyArg.getObject() )", callerReference, type)); } return(retObject); } catch (MethodInvocationException mie) { /* * not ideal, but otherwise we propagate 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 */ runtimeServices.Error(string.Format("VMProxyArg.getObject() : method invocation error getting value : {0}", mie)); return(null); } }
/// <summary> Evaluate the argument, convert to a String, and Evaluate again /// (with the same context). /// </summary> /// <param name="context"> /// </param> /// <param name="writer"> /// </param> /// <param name="node"> /// </param> /// <returns> True if the directive rendered successfully. /// </returns> /// <throws> IOException </throws> /// <throws> ResourceNotFoundException </throws> /// <throws> ParseErrorException </throws> /// <throws> MethodInvocationException </throws> public override bool Render(IInternalContextAdapter context, System.IO.TextWriter writer, INode node) { /* * Evaluate the string with the current context. We know there is * exactly one argument and it is a string or reference. */ object value = node.GetChild(0).Value(context); string sourceText; if (value != null) { sourceText = value.ToString(); } else { sourceText = ""; } /* * The new string needs to be parsed since the text has been dynamically generated. */ string templateName = context.CurrentTemplateName; SimpleNode nodeTree = null; try { nodeTree = rsvc.Parse(new StringReader(sourceText), templateName, false); } catch (ParseException pex) { // use the line/column from the template Info info = new Info(templateName, node.Line, node.Column); throw new ParseErrorException(pex.Message, info); } catch (TemplateInitException pex) { Info info = new Info(templateName, node.Line, node.Column); throw new ParseErrorException(pex.Message, info); } /* * now we want to Init and render. Chain the context * to prevent any changes to the current context. */ if (nodeTree != null) { IInternalContextAdapter ica = new EvaluateContext(context, rsvc); ica.PushCurrentTemplateName(templateName); try { try { nodeTree.Init(ica, rsvc); } catch (TemplateInitException pex) { Info info = new Info(templateName, node.Line, node.Column); throw new ParseErrorException(pex.Message, info); } try { /* * now render, and let any exceptions fly */ nodeTree.Render(ica, writer); } catch (ParseErrorException pex) { // convert any parsing errors to the correct line/col Info info = new Info(templateName, node.Line, node.Column); throw new ParseErrorException(pex.Message, info); } } finally { ica.PopCurrentTemplateName(); } return(true); } return(false); }
/// <summary> Renders the macro using the context. /// /// </summary> /// <param name="context">Current rendering context /// </param> /// <param name="writer">Writer for output /// </param> /// <param name="node">AST that calls the macro /// </param> /// <returns> True if the directive rendered successfully. /// </returns> /// <throws> IOException </throws> /// <throws> MethodInvocationException </throws> /// <throws> MacroOverflowException </throws> public override bool Render(IInternalContextAdapter context, System.IO.TextWriter writer, INode node) { // wrap the current context and Add the macro arguments // the creation of this context is a major bottleneck (incl 2x HashMap) //UPGRADE_NOTE: Final 已从“vmc ”的声明中移除。 "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" ProxyVMContext vmc = new ProxyVMContext(context, rsvc, localContextScope); int callArguments = node.GetNumChildren(); if (callArguments > 0) { // the 0th element is the macro name for (int i = 1; i < argArray.Length && i <= callArguments; i++) { INode macroCallArgument = node.GetChild(i - 1); /* * literalArgArray[i] is needed for "render literal if null" functionality. * The value is used in ASTReference render-method. * * The idea is to avoid generating the literal until absolutely necessary. * * This makes VMReferenceMungeVisitor obsolete and it would not work anyway * when the macro AST is shared */ vmc.AddVMProxyArg(context, argArray[i], literalArgArray[i], macroCallArgument); } } /* * check that we aren't already at the max call depth */ if (maxCallDepth > 0 && maxCallDepth == vmc.CurrentMacroCallDepth) { string templateName = vmc.CurrentTemplateName; object[] stack = vmc.MacroNameStack; System.Text.StringBuilder out_Renamed = new System.Text.StringBuilder(100).Append("Max calling depth of ").Append(maxCallDepth).Append(" was exceeded in Template:").Append(templateName).Append(" and Macro:").Append(macroName).Append(" with Call Stack:"); for (int i = 0; i < stack.Length; i++) { if (i != 0) { out_Renamed.Append("->"); } out_Renamed.Append(stack[i]); } rsvc.Log.Error(out_Renamed); try { throw new MacroOverflowException(out_Renamed.ToString()); } finally { // clean out the macro stack, since we just broke it while (vmc.CurrentMacroCallDepth > 0) { vmc.PopCurrentMacroName(); } } } try { // render the velocity macro vmc.PushCurrentMacroName(macroName); nodeTree.Render(vmc, writer); vmc.PopCurrentMacroName(); return(true); } catch (System.SystemException e) { throw e; } catch (System.Exception e) { string msg = "VelocimacroProxy.render() : exception VM = #" + macroName + "()"; rsvc.Log.Error(msg, e); throw new VelocityException(msg, e); } }