[ 
https://issues.apache.org/jira/browse/VELOCITY-586?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12628269#action_12628269
 ] 

Nathan Bubna commented on VELOCITY-586:
---------------------------------------

Is this stuff that could be done with an IncludeEventHandler?

> Add debugging hooks to #parse
> -----------------------------
>
>                 Key: VELOCITY-586
>                 URL: https://issues.apache.org/jira/browse/VELOCITY-586
>             Project: Velocity
>          Issue Type: Improvement
>          Components: Engine
>    Affects Versions: 1.5
>            Reporter: Tim White
>            Priority: Minor
>
> When you have a page that is made up of a complex web of templates and 
> #parsed includes, it is critical to be able to quickly see what parts of the 
> page are really in what file.
> To do this, I've hacked #parse to inject debugging information into the 
> template when a 'debug mode' is engaged.  This debug mode is engaged via a 
> URL parameter.
> I also inject this information in the VVS right before the main template is 
> rendered.  In this way, you can create a debug overlay on top of the page in 
> your browser that shows you where each piece of text is coming from.
> I think this probably could better be implemented using hooks, so that a user 
> could trigger when the debug information was being injected.
> I also suggest that the name of the current template, it's resource loader, 
> etc. be passed into the context, so it can be used to see what template is 
> where and what loader it came from.
> Finally, if there could be a way to conditionally prepend or append a 
> template to each merged or #parse template, that could also help.
> Thanks!!!
> package org.apache.velocity.runtime.directive;
> /*
>  * Licensed to the Apache Software Foundation (ASF) under one
>  * or more contributor license agreements.  See the NOTICE file
>  * distributed with this work for additional information
>  * regarding copyright ownership.  The ASF licenses this file
>  * to you under the Apache License, Version 2.0 (the
>  * "License"); you may not use this file except in compliance
>  * with the License.  You may obtain a copy of the License at
>  *
>  *   http://www.apache.org/licenses/LICENSE-2.0
>  *
>  * Unless required by applicable law or agreed to in writing,
>  * software distributed under the License is distributed on an
>  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
>  * KIND, either express or implied.  See the License for the
>  * specific language governing permissions and limitations
>  * under the License.    
>  */
> import java.io.IOException;
> import java.io.Writer;
> import javax.servlet.http.HttpSession;
> import org.apache.velocity.Template;
> import org.apache.velocity.app.event.EventHandlerUtil;
> import org.apache.velocity.context.InternalContextAdapter;
> import org.apache.velocity.exception.MethodInvocationException;
> import org.apache.velocity.exception.ParseErrorException;
> import org.apache.velocity.exception.ResourceNotFoundException;
> import org.apache.velocity.runtime.RuntimeConstants;
> import org.apache.velocity.runtime.parser.node.Node;
> import org.apache.velocity.runtime.parser.node.SimpleNode;
> import com.qwest.velocity.VelocityConstants;
> /**
>  * Pluggable directive that handles the <code>#parse()</code> statement in 
> VTL.
>  * 
>  * <pre>
>  *  Notes:
>  *  -----
>  *   1) The parsed source material can only come from somewhere in
>  *     the TemplateRoot tree for security reasons. There is no way
>  *     around this.  If you want to include content from elsewhere on
>  *     your disk, use a link from somwhere under Template Root to that
>  *     content.
>  * 
>  *   2) There is a limited parse depth.  It is set as a property
>  *     &quot;parse_directive.maxdepth = 10&quot;  for example.  There is a 20 
> iteration
>  *     safety in the event that the parameter isn't set.
>  * </pre>
>  * 
>  * @author <a href="mailto:[EMAIL PROTECTED]">Geir Magnusson Jr.</a>
>  * @author <a href="mailto:[EMAIL PROTECTED]">Jason van Zyl</a>
>  * @author <a href="mailto:[EMAIL PROTECTED]">Christoph Reck</a>
>  * @version $Id: Parse.java 463298 2006-10-12 16:10:32Z henning $
>  */
> public class Parse extends InputBase {
>       /**
>        * Return name of this directive.
>        * 
>        * @return The name of this directive.
>        */
>       public String getName() {
>               return "parse";
>       }
>       /**
>        * Return type of this directive.
>        * 
>        * @return The type of this directive.
>        */
>       public int getType() {
>               return LINE;
>       }
>       /**
>        * iterates through the argument list and renders every argument that 
> is appropriate. Any non appropriate arguments are logged, but render() 
> continues.
>        * 
>        * @param context
>        * @param writer
>        * @param node
>        * @return True if the directive rendered successfully.
>        * @throws IOException
>        * @throws ResourceNotFoundException
>        * @throws ParseErrorException
>        * @throws MethodInvocationException
>        */
>       public boolean render(InternalContextAdapter context, Writer writer, 
> Node node) throws IOException, ResourceNotFoundException, 
> ParseErrorException, MethodInvocationException {
>               /*
>                * if rendering is no longer allowed (after a stop), we can 
> safely skip execution of all the parse directives.
>                */
>               if (!context.getAllowRendering()) {
>                       return true;
>               }
>               /*
>                * did we get an argument?
>                */
>               if (node.jjtGetChild(0) == null) {
>                       rsvc.getLog().error("Portal #parse() null argument");
>                       return false;
>               }
>               /*
>                * does it have a value? If you have a null reference, then no.
>                */
>               Object value = node.jjtGetChild(0).value(context);
>               if (value == null) {
>                       rsvc.getLog().error("Portal #parse() null argument");
>                       return false;
>               }
>               /*
>                * get the path
>                */
>               String sourcearg = value.toString();
>               /*
>                * check to see if the argument will be changed by the event 
> cartridge
>                */
>               String arg = EventHandlerUtil.includeEvent(rsvc, context, 
> sourcearg, context.getCurrentTemplateName(), getName());
>               /*
>                * a null return value from the event cartridge indicates we 
> should not input a resource.
>                */
>               boolean blockinput = false;
>               if (arg == null)
>                       blockinput = true;
>               /*
>                * see if we have exceeded the configured depth. If it isn't 
> configured, put a stop at 20 just in case.
>                */
>               Object[] templateStack = context.getTemplateNameStack();
>               if (templateStack.length >= 
> rsvc.getInt(RuntimeConstants.PARSE_DIRECTIVE_MAXDEPTH, 20)) {
>                       StringBuffer path = new StringBuffer();
>                       for (int i = 0; i < templateStack.length; ++i) {
>                               path.append(" > " + templateStack[i]);
>                       }
>                       rsvc.getLog().error("Portal #parse: Max recursion depth 
> reached (" + templateStack.length + ')' + " File stack:" + path);
>                       return false;
>               }
>               /*
>                * now use the Runtime resource loader to get the template
>                */
>               Template t = null;
>               try {
>                       if (!blockinput)
>                               t = rsvc.getTemplate(arg, 
> getInputEncoding(context));
>               } catch (ResourceNotFoundException rnfe) {
>                       /*
>                        * the arg wasn't found. Note it and throw
>                        */
>                       rsvc.getLog().error("Portal #parse(): cannot find 
> template '" + arg + "', called from template " + 
> context.getCurrentTemplateName() + " at (" + getLine() + ", " + getColumn() + 
> ")");
>                       throw rnfe;
>               } catch (ParseErrorException pee) {
>                       /*
>                        * the arg was found, but didn't parse - syntax error 
> note it and throw
>                        */
>                       rsvc.getLog().error(
>                                       "Portal #parse(): syntax error in 
> #parse()-ed template '" + arg + "', called from template " + 
> context.getCurrentTemplateName() + " at (" + getLine() + ", " + getColumn() + 
> ")");
>                       throw pee;
>               }
>               /**
>                * pass through application level runtime exceptions
>                */
>               catch (RuntimeException e) {
>                       throw e;
>               } catch (Exception e) {
>                       rsvc.getLog().error("Portal #parse() : arg = " + arg + 
> '.', e);
>                       return false;
>               }
>               /*
>                * and render it
>                */
>               try {
>                       if (rsvc.getLog().isDebugEnabled()) {
>                               rsvc.getLog().debug("*** Portal #Parse Template 
> Path: " + t.getName());
>                       }
>                       
>                       /* Save the name of the main template before resetting 
> templateName for this include */
>                       String mainTemplateName = "";
>                       if (context.get(VelocityConstants.TEMPLATE_NAME_VAR) != 
> null) {
>                               mainTemplateName = 
> context.get(VelocityConstants.TEMPLATE_NAME_VAR).toString();
>                       }
>                       /* Set the name of the current template in the context 
> for general use */
>                       context.put(VelocityConstants.TEMPLATE_NAME_VAR, 
> t.getName());
>                       /* Check various places to see if debug mode is enabled 
> */
>                       boolean debugMode = false;
>                       /* This supports PortalVelocityViewServlet */
>                       if (context.get(VelocityConstants.DEBUG_ATTRIBUTE) != 
> null) {
>                               debugMode = true;
>                       }
>                       /* This supports qcms.getMessage() */
>                       if (context.get("session") != null) {
>                               HttpSession session = (HttpSession) 
> context.get("session");
>                               if (session.getAttribute("qCmsDebugger") != 
> null) {
>                                       debugMode = true;
>                               }
>                       }
>                       /* Print Debug start output to browser if debug mode is 
> on */
>                       if (debugMode) {
>                               Template startTemplate = 
> rsvc.getTemplate(VelocityConstants.DEBUG_OUTLINE_START_TEMPLATE, 
> getInputEncoding(context));
>                               startTemplate.merge(context, writer);
>                               Template nameTemplate = 
> rsvc.getTemplate(VelocityConstants.DEBUG_NAME_TEMPLATE, 
> getInputEncoding(context));
>                               nameTemplate.merge(context, writer);
>                       }
>                       
>                       if (!blockinput) {
>                               context.pushCurrentTemplateName(arg);
>                               ((SimpleNode) t.getData()).render(context, 
> writer);
>                       }
>                       
>                       /* Print Debug end output to browser if debug mode is 
> on */
>                       if (debugMode) {
>                               Template endTemplate = 
> rsvc.getTemplate(VelocityConstants.DEBUG_OUTLINE_END_TEMPLATE, 
> getInputEncoding(context));
>                               endTemplate.merge(context, writer);
>                       }
>                       /* Restore the templateName variable to match the main 
> template name */
>                       context.put(VelocityConstants.TEMPLATE_NAME_VAR, 
> mainTemplateName);
>               }
>               /*
>                * if it's a MIE, it came from the render.... throw it...
>                */
>               catch (MethodInvocationException e) {
>                       throw e;
>               }
>               /**
>                * pass through application level runtime exceptions
>                */
>               catch (RuntimeException e) {
>                       throw e;
>               }
>               catch (Exception e) {
>                       rsvc.getLog().error("Portal #parse: Exception rendering 
> #parse(" + arg + ')', e);
>                       return false;
>               } finally {
>                       if (!blockinput)
>                               context.popCurrentTemplateName();
>               }
>               /*
>                * note - a blocked input is still a successful operation as 
> this is expected behavior.
>                */
>               return true;
>       }
> }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to