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