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.log.Log;
24  import org.apache.velocity.runtime.parser.ParseException;
25  import org.apache.velocity.runtime.parser.Token;
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: MacroParseException.java 703544 2008-10-10 18:15:53Z nbubna $
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       */
52      public MacroParseException(final String msg, final String templateName, final Token currentToken)
53      {
54          super(msg);
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      public String getTemplateName()
65      {
66          return templateName;
67      }
68  
69      /**
70       * returns the line number where this exception occured.
71       * @return The line number where this exception occured.
72       * @since 1.5
73       */
74      public int getLineNumber()
75      {
76          if ((currentToken != null) && (currentToken.next != null))
77          {
78              return currentToken.next.beginLine;
79          }
80          else
81          {
82              return -1;
83          }
84      }
85  
86      /**
87       * returns the column number where this exception occured.
88       * @return The column number where this exception occured.
89       * @since 1.5
90       */
91      public int getColumnNumber()
92      {
93          if ((currentToken != null) && (currentToken.next != null))
94          {
95              return currentToken.next.beginColumn;
96          }
97          else
98          {
99              return -1;
100         }
101     }
102 
103     /**
104      * This method has the standard behavior when this object has been
105      * created using the standard constructors.  Otherwise, it uses
106      * "currentToken" and "expectedTokenSequences" to generate a parse
107      * error message and returns it.  If this object has been created
108      * due to a parse error, and you do not catch it (it gets thrown
109      * from the parser), then this method is called during the printing
110      * of the final stack trace, and hence the correct error message
111      * gets displayed.
112      * @return the current message.
113      * @since 1.5
114      */
115     public String getMessage()
116     {
117         if (!specialConstructor)
118         {
119             StringBuffer sb = new StringBuffer(super.getMessage());
120             appendTemplateInfo(sb);
121             return sb.toString();
122         }
123 
124         int maxSize = 0;
125 
126         StringBuffer expected = new StringBuffer();
127 
128         for (int i = 0; i < expectedTokenSequences.length; i++)
129         {
130             if (maxSize < expectedTokenSequences[i].length)
131             {
132                 maxSize = expectedTokenSequences[i].length;
133             }
134 
135             for (int j = 0; j < expectedTokenSequences[i].length; j++)
136             {
137                 expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" ");
138             }
139 
140             if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0)
141             {
142                 expected.append("...");
143             }
144 
145             expected.append(eol).append("    ");
146         }
147 
148         StringBuffer retval = new StringBuffer("Encountered \"");
149         Token tok = currentToken.next;
150 
151         for (int i = 0; i < maxSize; i++)
152         {
153             if (i != 0)
154             {
155                 retval.append(" ");
156             }
157 
158             if (tok.kind == 0)
159             {
160                 retval.append(tokenImage[0]);
161                 break;
162             }
163 
164             retval.append(add_escapes(tok.image));
165             tok = tok.next;
166         }
167 
168         retval.append("\"");
169         appendTemplateInfo(retval);
170 
171         if (expectedTokenSequences.length == 1)
172         {
173             retval.append("Was expecting:").append(eol).append("    ");
174         }
175         else
176         {
177             retval.append("Was expecting one of:").append(eol).append("    ");
178         }
179 
180         // avoid JDK 1.3 StringBuffer.append(Object o) vs 1.4 StringBuffer.append(StringBuffer sb) gotcha.
181         retval.append(expected.toString());
182         return retval.toString();
183     }
184 
185     /**
186      * @param sb
187      * @since 1.5
188      */
189     protected void appendTemplateInfo(final StringBuffer sb)
190     {
191         sb.append(Log.formatFileString(getTemplateName(), getLineNumber(), getColumnNumber()));
192         sb.append(eol);
193     }
194 }