• 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.exception.ExtendedParseException;
23 import org.apache.velocity.runtime.parser.ParseException;
24 import org.apache.velocity.runtime.parser.Token;
25 import org.apache.velocity.util.StringUtils;
26 
27 /**
28  *  Exception to indicate problem happened while constructing #macro()
29  *
30  *  For internal use in parser - not to be passed to app level
31  *
32  * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
33  * @author <a href="hps@intermeta.de">Henning P. Schmiedehausen</a>
34  * @version $Id$
35  */
36 public class MacroParseException
37         extends ParseException
38         implements ExtendedParseException
39 {
40     private final String templateName;
41 
42     /**
43      * Version Id for serializable
44      */
45     private static final long serialVersionUID = -4985224672336070689L;
46 
47     /**
48      * @param msg
49      * @param templateName
50      * @param currentToken
51      */
MacroParseException(final String msg, final String templateName, final Token currentToken)52     public MacroParseException(final String msg, final String templateName, final Token currentToken)
53     {
54         super(msg + " at ");
55         this.currentToken = currentToken;
56         this.templateName = templateName;
57     }
58 
59     /**
60      * returns the Template name where this exception occured.
61      * @return The Template name where this exception occured.
62      * @since 1.5
63      */
64     @Override
getTemplateName()65     public String getTemplateName()
66     {
67         return templateName;
68     }
69 
70     /**
71      * returns the line number where this exception occured.
72      * @return The line number where this exception occured.
73      * @since 1.5
74      */
75     @Override
getLineNumber()76     public int getLineNumber()
77     {
78         if ((currentToken != null) && (currentToken.next != null))
79         {
80             return currentToken.next.beginLine;
81         }
82         else if (currentToken != null)
83         {
84             return currentToken.beginLine;
85         }
86         else
87         {
88             return -1;
89         }
90     }
91 
92     /**
93      * returns the column number where this exception occured.
94      * @return The column number where this exception occured.
95      * @since 1.5
96      */
97     @Override
getColumnNumber()98     public int getColumnNumber()
99     {
100         if ((currentToken != null) && (currentToken.next != null))
101         {
102             return currentToken.next.beginColumn;
103         }
104         else if (currentToken != null)
105         {
106             return currentToken.beginColumn;
107         }
108         else
109         {
110             return -1;
111         }
112     }
113 
114     /**
115      * This method has the standard behavior when this object has been
116      * created using the standard constructors.  Otherwise, it uses
117      * "currentToken" and "expectedTokenSequences" to generate a parse
118      * error message and returns it.  If this object has been created
119      * due to a parse error, and you do not catch it (it gets thrown
120      * from the parser), then this method is called during the printing
121      * of the final stack trace, and hence the correct error message
122      * gets displayed.
123      * @return the current message.
124      * @since 1.5
125      */
126     @Override
getMessage()127     public String getMessage()
128     {
129         if (!specialConstructor)
130         {
131             StringBuilder sb = new StringBuilder(super.getMessage());
132             appendTemplateInfo(sb);
133             return sb.toString();
134         }
135 
136         int maxSize = 0;
137 
138         StringBuilder expected = new StringBuilder();
139 
140         for (int[] expectedTokenSequence : expectedTokenSequences)
141         {
142             if (maxSize < expectedTokenSequence.length)
143             {
144                 maxSize = expectedTokenSequence.length;
145             }
146 
147             for (int i : expectedTokenSequence)
148             {
149                 expected.append(tokenImage[i]).append(" ");
150             }
151 
152             if (expectedTokenSequence[expectedTokenSequence.length - 1] != 0)
153             {
154                 expected.append("...");
155             }
156 
157             expected.append(eol).append("    ");
158         }
159 
160         StringBuilder retval = new StringBuilder("Encountered \"");
161         Token tok = currentToken.next;
162 
163         for (int i = 0; i < maxSize; i++)
164         {
165             if (i != 0)
166             {
167                 retval.append(" ");
168             }
169 
170             if (tok.kind == 0)
171             {
172                 retval.append(tokenImage[0]);
173                 break;
174             }
175 
176             retval.append(add_escapes(tok.image));
177             tok = tok.next;
178         }
179 
180         retval.append("\"");
181         appendTemplateInfo(retval);
182 
183         if (expectedTokenSequences.length == 1)
184         {
185             retval.append("Was expecting:").append(eol).append("    ");
186         }
187         else
188         {
189             retval.append("Was expecting one of:").append(eol).append("    ");
190         }
191 
192         // avoid JDK 1.3 StringBuffer.append(Object o) vs 1.4 StringBuffer.append(StringBuffer sb) gotcha.
193         retval.append(expected.toString());
194         return retval.toString();
195     }
196 
197     /**
198      * @param sb
199      * @since 1.5
200      */
appendTemplateInfo(final StringBuilder sb)201     protected void appendTemplateInfo(final StringBuilder sb)
202     {
203         sb.append(StringUtils.formatFileString(getTemplateName(), getLineNumber(), getColumnNumber()));
204         sb.append(eol);
205     }
206 }
207