Re: partial evaluation / removing directives
Pete <[email protected]>
| Newsgroups | gmane.comp.jakarta.velocity.user |
|---|---|
| Message-ID | <CAFsY3T6vk282h-m6ZN4nncwhv5seXupqP_15KLuB+xF3kqfayw@mail.gmail.com> |
Oops, just managed to just get around this with a tiny class decorating ClasspathResourceLoader and setting that new class as the loader in the properties. Not sure about that String loader class but I don't need it for now. On Thu, Jul 19, 2012 at 9:59 AM, Pete <[email protected]> wrote: > Hey, quick question re: modifying the resource loader .. I think I'm going > to go with this solution since regexp replace seems to work well, hence if > I can intercept the vm files and fix them before velocity references them > I'll be in good shape. > > The way I tried to do this so far is as follows: > > > StringResourceLoader.setRepository(StringResourceLoader.REPOSITORY_NAME_DEFAULT,new > StringResourceRepositoryImpl()); > instance = new Velocity(); > Velocity.setProperty(Velocity.FILE_RESOURCE_LOADER_CACHE, false); > > Velocity.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, > TEMPLATE_LOCATION); > > Velocity.addProperty(Velocity.RESOURCE_LOADER, "classpath"); > Velocity.addProperty(Velocity.RUNTIME_REFERENCES_STRICT + > ".escape","true"); > Velocity.setProperty("classpath." + Velocity.RESOURCE_LOADER + > ".class", > ClasspathResourceLoader.class.getName()); > Velocity.setProperty("classpath." + Velocity.RESOURCE_LOADER + > ".cache", "false"); > Velocity.setProperty("classpath." + Velocity.RESOURCE_LOADER + > ".modificationCheckInterval", "2"); > Velocity.setProperty("loader", "string"); > Velocity.setProperty("string.resource.loader.class", > "org.apache.velocity.runtime.resource.loader.StringResourceLoader"); > > Velocity.setProperty("string.resource.loader.repository.class","org.apache.velocity.runtime.resource.util.StringResourceRepositoryImpl"); > Velocity.init(); > > > Following this, I iterate over all my known velocity templates and try to > put them in the string resource loader repository, using something like > this > repository.putStringResource((template path + name), > sanitizedAlert); > it was my understanding that putting these in, when I then call > mergeTemplate(), rather than using the files on the hard drive it would use > the copies in this resource loader repository. > However, it seems to still default to checking the classpath file loader, > and debugging in I didn't see any sort of conditonal check based on any of > the properties I set which wold make it use this resource loader repository > instead. > > Am I doing this totally wrong? Is the String Resource Loader Repository > not what I want here? > > thanks, > Pete > > > On Fri, Jul 13, 2012 at 11:25 AM, Nathan Bubna <[email protected]> wrote: > >> On Fri, Jul 13, 2012 at 8:12 AM, Pete <[email protected]> wrote: >> > Thanks for the info guys. To answer that one question >> >> Why would evaluate cause problems for #parse?? If the engine is >> >> configured the same, the #parse should work the same whether you enter >> >> via file or string. >> > The problem would be even if the #parse directives get picked up OK in >> my >> > in-memory, preprocessed string version of the file (since I set template >> > location path), Velocity would just go and consume those additional >> > template files on its own, not giving me a chance to preprocess them >> first. >> > Maybe I could avoid this if there was way to extend /replacevelocity's >> > template file loader, I haven't looked at the code enough to know if >> this >> > is possible >> >> oh yeah, duh. and yes, you can definitely make your own resource >> loaders. those are pluggable. :) >> >> > That's an interesting suggestion re: the other templating Engine... I >> > considered trying to home-brew my own (just looking for those two >> > directives), but it seemed like a waste since there's already such >> powerful >> > and robust ones out there. Also, there'sa bit of subtley there since it >> can >> > be recursive ($resourceBundles can themselves include references to >> #parse, >> > which can include references to resource bundles, etc). If there was a >> > really simple, customizable template engine one that would let me choose >> > exactly what was parsed, that would probably be best. >> >> Hmm. i'm not aware of one, but i'm much less active in this space >> than i used to be. >> >> > My only issue using >> > another one similar in size to velocity is that there might be some >> "side >> > effects", eg statements which are ignored by velocity but which get >> > interpreted somehow through this other engine due to its own particular >> > syntax. >> >> yeah, that's a concern. >> >> > As for the AST rewrite idea, if it was possible to "Burn down" nodes to >> > their corresponding text something like that would work, However, >> wouldnt' >> > that then possibly miss additional child elements in that AST tree? For >> > instance a clause in an if statement which had a resourceBundle >> reference? >> > I'm not too familiar with ASTs (been years since I dealt with those at >> > school), maybe I can look at it a bit more today. >> >> worth a look. it sounded like a reasonable approach to me. >> definitely easier than trying to remove baked-in directives. >> >> > >> > thanks, >> > Pete >> > >> > On Fri, Jul 13, 2012 at 9:57 AM, Alex Fedotov <[email protected]> wrote: >> > >> >> Another option may be rewriting the AST tree after the template is >> parsed >> >> and replacing some nodes with text or something else. >> >> I tried that on the side as an experiment to inject some security >> checks >> >> and collect profiling info for macros and templates. >> >> >> >> Alex >> >> >> >> >> >> >> >> On Fri, Jul 13, 2012 at 9:50 AM, Nathan Bubna <[email protected]> >> wrote: >> >> >> >> > On Thu, Jul 12, 2012 at 2:27 PM, Pete <[email protected]> >> wrote: >> >> > > Hi all, >> >> > > I'm working with some velocity files where I want to partially >> evaluate >> >> > > them, such that the only things actually evaluated are #parse >> (includes >> >> > of >> >> > > other velocity templates in the same directory) and $references >> to a >> >> > > resourceBundle variable passed in the context map. In essence, all >> >> this >> >> > is >> >> > > doing is combining a number of velocity files into one master >> velocity >> >> > > file, and localizing any resource bundle references to a given >> locale. >> >> > All >> >> > > the main velocity directives in the velocity file(s) should be left >> >> > > unevaluated- #set, #ifelse, #foreach etc. This way, the result >> could >> >> be >> >> > > redistributed and modified specific to a particular locale, with >> just >> >> one >> >> > > file instead of n based on the #parse structure. >> >> > >> >> > interesting challenge! glad i don't have to do it though. :) >> >> > >> >> > > Up till now, I've been doing this in a somewhat roundabout way: >> >> > > 1. setting strict escape property to true >> >> > > 2. pre-processing the velocity templates by regexp replacing all >> >> > instances >> >> > > of #if / #else/ #elseif/ #end / #foreach / #define / #break / #stop >> >> > #set / >> >> > > #evaluate with \\#{$1} >> >> > > This adds a an escape character before each of these directives, >> and I >> >> > can >> >> > > then call mergeTemplate on the result. It works OK, sometimes, >> but I >> >> > still >> >> > > run into some parsing issues now and again (eg not a robust >> solution). >> >> It >> >> > > also seems kind of heavy handed to have to preprocess these files >> >> using a >> >> > > regular expression and saving them before velocity gets a handle on >> >> them. >> >> > > It would even be a bit better if I could do this by reading them >> in and >> >> > > doing the rgexp in-memory rather than on the saved files, then >> using >> >> > > evaluate instead of mergeTemplate. But I assume that would cause >> >> problems >> >> > > for the #parse directives. >> >> > >> >> > Why would evaluate cause problems for #parse?? If the engine is >> >> > configured the same, the #parse should work the same whether you >> enter >> >> > via file or string. >> >> > >> >> > > I know velocity added a removeDirective() method in 1.6.2 which >> seems >> >> > like >> >> > > it should be perfect for me - I could simply rip out all the >> directives >> >> > but >> >> > > #parse. However, I tried the and it seems that it only works for >> >> certain >> >> > > directives, eg #foreach, #include, etc. More basic directives >> like >> >> #if >> >> > > and #elseif are not in the list of runtimedirectives, or even >> >> represented >> >> > > as Directive objects, so removing them doesn't work. >> >> > >> >> > Yeah, they are deep in the parser. Their structure doesn't work as a >> >> > normal directive. >> >> > >> >> > > Any suggestions on the best way to proceed with this? Would it be >> easy >> >> to >> >> > > change a few velocity files locally, recompile and get this >> behavior? >> >> Or >> >> > is >> >> > > it sufficiently complex removing all these more basic directives >> that >> >> I'm >> >> > > better off continuing to try some kind of preprocessing/ escaping? >> >> > >> >> > You would have to redesign Velocity's parsing deeply. A major >> >> > overhaul. You're best off preprocessing. Have you considered using >> >> > a different template engine to do the first part (the parse and >> >> > resourceBundle resolution)? Might be overkill, but might be easier, >> >> > so long as the syntax has no overlap with VTL. >> >> > >> >> > > thanks, >> >> > > Pete >> >> > >> >> > --------------------------------------------------------------------- >> >> > To unsubscribe, e-mail: [email protected] >> >> > For additional commands, e-mail: [email protected] >> >> > >> >> > >> >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: [email protected] >> For additional commands, e-mail: [email protected] >> >> >