Author: nbubna
Date: Mon Feb 23 16:21:48 2009
New Revision: 747067

URL: http://svn.apache.org/viewvc?rev=747067&view=rev
Log:
enforce #break must be in #foreach and refactor ASTStop and Break to properly 
use StopCommands

Modified:
    velocity/engine/trunk/src/java/org/apache/velocity/Template.java
    
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
    
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java
    
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Evaluate.java
    
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java
    
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTStop.java

Modified: velocity/engine/trunk/src/java/org/apache/velocity/Template.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/Template.java?rev=747067&r1=747066&r2=747067&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/Template.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/Template.java Mon Feb 23 
16:21:48 2009
@@ -39,7 +39,6 @@
 import org.apache.velocity.runtime.directive.StopCommand;
 import org.apache.velocity.runtime.parser.ParseException;
 import org.apache.velocity.runtime.parser.node.SimpleNode;
-import org.apache.velocity.runtime.parser.node.ASTStop.StopThrowable;
 import org.apache.velocity.runtime.resource.Resource;
 import org.apache.velocity.runtime.resource.ResourceManager;
 
@@ -363,14 +362,6 @@
                     throw stop;
                 }
             }
-            catch (StopThrowable st)
-            {
-              // The stop throwable is thrown by ASTStop (the #stop directive)
-              // The intent of the stop directive is to halt processing of the
-              // the template, so we throw a Throwable that will short circuit
-              // everthing between the call to render, and ASTStop. We just 
needed to 
-              // Catch the exception, nothing else to do.              
-            }
             catch (IOException e)
             {
                 throw new VelocityException("IO Error rendering template '"+ 
name + "'", e);

Modified: 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java?rev=747067&r1=747066&r2=747067&view=diff
==============================================================================
--- 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java 
(original)
+++ 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java 
Mon Feb 23 16:21:48 2009
@@ -57,7 +57,6 @@
 import org.apache.velocity.runtime.parser.Parser;
 import org.apache.velocity.runtime.parser.node.Node;
 import org.apache.velocity.runtime.parser.node.SimpleNode;
-import org.apache.velocity.runtime.parser.node.ASTStop.StopThrowable;
 import org.apache.velocity.runtime.resource.ContentResource;
 import org.apache.velocity.runtime.resource.ResourceManager;
 import org.apache.velocity.util.ClassUtils;
@@ -1372,14 +1371,6 @@
                     throw stop;
                 }
             }
-            catch (StopThrowable st)
-            {
-                // The stop throwable is thrown by ASTStop (the #stop 
directive)
-                // The intent of the stop directive is to halt processing of 
the
-                // the template, so we throw a Throwable that will short 
circuit
-                // everthing between this call to render, and ASTStop. We just 
needed to 
-                // Catch the exception, nothing else to do.              
-            }
             catch (IOException e)
             {
                 throw new VelocityException("IO Error in writer: " + 
e.getMessage(), e);

Modified: 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java?rev=747067&r1=747066&r2=747067&view=diff
==============================================================================
--- 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java 
(original)
+++ 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java 
Mon Feb 23 16:21:48 2009
@@ -21,24 +21,16 @@
 
 import java.io.IOException;
 import java.io.Writer;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.velocity.app.event.EventCartridge;
-import org.apache.velocity.context.Context;
 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.exception.TemplateInitException;
-import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.exception.VelocityException;
 import org.apache.velocity.runtime.RuntimeServices;
-import org.apache.velocity.runtime.parser.node.ASTReference;
+import org.apache.velocity.runtime.log.Log;
+import org.apache.velocity.runtime.parser.node.ASTDirective;
 import org.apache.velocity.runtime.parser.node.Node;
-import org.apache.velocity.runtime.parser.node.SimpleNode;
-import org.apache.velocity.runtime.resource.Resource;
-import org.apache.velocity.util.introspection.Info;
-import org.apache.velocity.util.introspection.IntrospectionCacheData;
 
 /**
  * Break directive used for interrupting foreach loops.
@@ -48,7 +40,7 @@
  */
 public class Break extends Directive
 {
-    private static final RuntimeException BREAK = new BreakException();
+    private static final BreakCommand BREAK = new BreakCommand();
     /**
      * Return name of this directive.
      * @return The name of this directive.
@@ -88,12 +80,26 @@
         throws TemplateInitException
     {
         super.init(rs, context, node);
+
+        // Make sure the #break directive is within a foreach block.
+        Node check = node;
+        while (!(check instanceof ASTDirective) ||
+               !((ASTDirective)check).getDirectiveName().equals("foreach"))
+        {
+            check = check.jjtGetParent();
+            if (check == null)
+            {
+                // We are not in a macro definition, so throw an exception.
+                throw new VelocityException("#break must be within a #foreach 
block at " 
+                    + Log.formatFileString(this));
+            }
+        }
     }
 
     /**
      * Break directive does not actually do any rendering. 
      * 
-     * This directive throws a BreakException (RuntimeException) which
+     * This directive throws a BreakCommand which
      * signals foreach directive to break out of the loop. Note that this
      * directive does not verify that it is being called inside a foreach
      * loop.
@@ -115,14 +121,21 @@
         throw BREAK;
     }
     
-    public static class BreakException extends RuntimeException 
+    /**
+     * Specialized StopCommand that stops the nearest #foreach loop.
+     */
+    public static class BreakCommand extends StopCommand 
     {
-        public BreakException()
+        public BreakCommand()
+        {
+            // If a break is thrown during a macro or parse call, then this 
exception
+            // will eventually be seen, so provide the user with some info.
+            super("closest #foreach loop");
+        }
+
+        public boolean isFor(Object that)
         {
-          // If a break is thrown during a macro or parse call, then this 
exception
-          // will be logged because this method calls catch
-          // RuntimeException, so provide the user with some info.
-          super("Break");
+            return (that instanceof Foreach);
         }
     }
 }

Modified: 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Evaluate.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Evaluate.java?rev=747067&r1=747066&r2=747067&view=diff
==============================================================================
--- 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Evaluate.java
 (original)
+++ 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Evaluate.java
 Mon Feb 23 16:21:48 2009
@@ -35,7 +35,6 @@
 import org.apache.velocity.runtime.parser.ParserTreeConstants;
 import org.apache.velocity.runtime.parser.node.Node;
 import org.apache.velocity.runtime.parser.node.SimpleNode;
-import org.apache.velocity.runtime.parser.node.ASTStop.StopThrowable;
 import org.apache.velocity.util.introspection.Info;
 
 /**
@@ -212,14 +211,6 @@
                         throw stop;
                     }
                 }
-                catch (StopThrowable st)
-                {
-                    // The stop throwable is thrown by ASTStop (the #stop 
directive)
-                    // The intent of the stop directive is to halt processing 
of the
-                    // the template, so we throw a Throwable that will short 
circuit
-                    // everthing between this node, and ASTStop. We just 
needed to 
-                    // Catch the exception, nothing else to do.
-                }
                 catch (ParseErrorException pex)
                 {
                     // convert any parsing errors to the correct line/col

Modified: 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java?rev=747067&r1=747066&r2=747067&view=diff
==============================================================================
--- 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java
 (original)
+++ 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java
 Mon Feb 23 16:21:48 2009
@@ -397,11 +397,6 @@
                     throw stop;
                 }
             }
-            catch (Break.BreakException ex)
-            {
-                // encountered #break directive inside #foreach loop
-                break;
-            }
             
             counter++;
 

Modified: 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTStop.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTStop.java?rev=747067&r1=747066&r2=747067&view=diff
==============================================================================
--- 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTStop.java
 (original)
+++ 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTStop.java
 Mon Feb 23 16:21:48 2009
@@ -21,13 +21,17 @@
 
 import java.io.IOException;
 import java.io.Writer;
-
+import org.apache.velocity.Template;
 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.RuntimeInstance;
+import org.apache.velocity.runtime.directive.Evaluate;
+import org.apache.velocity.runtime.directive.StopCommand;
 import org.apache.velocity.runtime.parser.Parser;
 
+
 /**
  * This class is responsible for handling the #stop directive
  *
@@ -40,6 +44,8 @@
  */
 public class ASTStop extends SimpleNode
 {
+    private static final StopCommand STOP = new StopAllCommand();
+
     /**
      * @param id
      */
@@ -80,17 +86,29 @@
     {
         // The top level calls that render an AST node tree catch this 
Throwable.  By throwing
         // Here we terminate rendering of this node tree.
-        throw new StopThrowable();        
+        throw STOP;        
     }
-    
+
     /**
-     * We select to overide Error here intead of RuntimeInstance because there 
are
-     * certain nodes that catch RuntimeException when rendering there 
children, and log
-     * the event to error.  But of course in the case that the template 
renders an ASTStop
-     * node we don't want this to happen.
+     * Specialized StopCommand that stops all merge or evaluate activity.
      */
-    public static class StopThrowable extends Error
-    {      
+    public static class StopAllCommand extends StopCommand
+    {
+        public StopAllCommand()
+        {
+            super("Template.merge or RuntimeInstance.evaluate");
+        }
+
+        public boolean isFor(Object that)
+        {
+            return (that instanceof Template ||
+                    that instanceof RuntimeInstance ||
+                    //FIXME: #evaluate probably shouldn't catch #stop()
+                    //       since it isn't truly top-level, but that's
+                    //       how it was currently designed.
+                    that instanceof Evaluate);
+        }
     }
+
 }
 


Reply via email to