View Javadoc

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