• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.apache.velocity.runtime.directive;
2 
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  *   http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21 
22 import org.apache.velocity.context.InternalContextAdapter;
23 import org.apache.velocity.runtime.RuntimeServices;
24 import org.apache.velocity.runtime.parser.ParseException;
25 import org.apache.velocity.runtime.parser.Token;
26 import org.apache.velocity.runtime.parser.node.Node;
27 
28 import java.io.Writer;
29 import java.util.ArrayList;
30 
31 /**
32  * This class implements the #stop directive which allows
33  * a user to stop the merging and rendering process. The #stop directive
34  * will accept a single message argument with info about the reason for
35  * stopping.
36  */
37 public class Stop extends Directive
38 {
39     private static final StopCommand STOP_ALL = new StopCommand("StopCommand to exit merging") {
40         @Override
41         public synchronized Throwable fillInStackTrace() {
42             return this;
43         }
44     };
45 
46     private boolean hasMessage = false;
47 
48     /**
49      * Return name of this directive.
50      * @return The name of this directive.
51      */
52     @Override
getName()53     public String getName()
54     {
55         return "stop";
56     }
57 
58     /**
59      * Return type of this directive.
60      * @return The type of this directive.
61      */
62     @Override
getType()63     public int getType()
64     {
65         return LINE;
66     }
67 
68     /**
69      * Since there is no processing of content,
70      * there is never a need for an internal scope.
71      */
72     @Override
isScopeProvided()73     public boolean isScopeProvided()
74     {
75         return false;
76     }
77 
78     @Override
init(RuntimeServices rs, InternalContextAdapter context, Node node)79     public void init(RuntimeServices rs, InternalContextAdapter context, Node node)
80     {
81         super.init(rs, context, node);
82 
83         hasMessage = (node.jjtGetNumChildren() == 1);
84     }
85 
86     @Override
render(InternalContextAdapter context, Writer writer, Node node)87     public boolean render(InternalContextAdapter context, Writer writer, Node node)
88     {
89         if (!hasMessage)
90         {
91             throw STOP_ALL;
92         }
93 
94         Object argument = node.jjtGetChild(0).value(context);
95 
96         // stop all and use specified message
97         throw new StopCommand(String.valueOf(argument));
98     }
99 
100     /**
101      * Called by the parser to check the argument types
102      */
103     @Override
checkArgs(ArrayList<Integer> argtypes, Token t, String templateName)104     public void checkArgs(ArrayList<Integer> argtypes, Token t, String templateName)
105       throws ParseException
106     {
107         int kids = argtypes.size();
108         if (kids > 1)
109         {
110             throw new MacroParseException("The #stop directive only accepts a single message parameter",
111                templateName, t);
112         }
113     }
114 
115 }
116