View Javadoc

1   package org.apache.velocity.exception;
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 java.util.regex.Matcher;
23  import java.util.regex.Pattern;
24  
25  import org.apache.velocity.runtime.log.Log;
26  import org.apache.velocity.runtime.parser.ParseException;
27  import org.apache.velocity.util.introspection.Info;
28  
29  /**
30   *  Application-level exception thrown when a resource of any type
31   *  has a syntax or other error which prevents it from being parsed.
32   *  <br>
33   *  When this resource is thrown, a best effort will be made to have
34   *  useful information in the exception's message.  For complete
35   *  information, consult the runtime log.
36   *
37   * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
38   * @author <a href="hps@intermeta.de">Henning P. Schmiedehausen</a>
39   * @version $Id: ParseErrorException.java 736638 2009-01-22 13:42:52Z byron $
40   */
41  public class ParseErrorException extends VelocityException
42  {
43      /**
44       * Version Id for serializable
45       */
46      private static final long serialVersionUID = -6665197935086306472L;
47  
48      /**
49       * The column number of the parsing error, or -1 if not defined.
50       */
51      private int columnNumber = -1;
52  
53      /**
54       * The line number of the parsing error, or -1 if not defined.
55       */
56      private int lineNumber = -1;
57  
58      /**
59       * The name of the template containing the error, or null if not defined.
60       */
61      private String templateName = "*unset*";
62  
63      /**
64       * If applicable, contains the invalid syntax or reference that triggered this exception
65       */
66      private String invalidSyntax;
67      
68      /**
69       * If we modify the message, then we set this
70       */
71      private String msg = null;
72  
73      /**
74       * Create a ParseErrorException with the given message.
75       *
76       * @param exceptionMessage the error exception message
77       */
78      public ParseErrorException(String exceptionMessage)
79      {
80            super(exceptionMessage);
81      }
82  
83      private static final Pattern lexError = Pattern.compile("Lexical error.*TokenMgrError.*line (\\d+),.*column (\\d+)\\.(.*)");
84      
85      /**
86       * Create a ParseErrorException with the given ParseException.
87       *
88       * @param pex the parsing exception
89       * @since 1.5
90       */
91      public ParseErrorException(ParseException pex, String templName)
92      {
93          super(pex.getMessage());
94          
95          if (templName != null) templateName = templName;
96  
97          // Don't use a second C'tor, TemplateParseException is a subclass of
98          // ParseException...
99          if (pex instanceof ExtendedParseException)
100         {
101             ExtendedParseException xpex = (ExtendedParseException) pex;
102 
103             columnNumber = xpex.getColumnNumber();
104             lineNumber = xpex.getLineNumber();
105             templateName = xpex.getTemplateName();
106         }
107         else
108         { 
109             // We get here if the the Parser has thrown an exception. Unfortunately,
110             // the error message created is hard coded by javacc, so here we alter
111             // the error message, so that it is in our standard format.          
112             Matcher match =  lexError.matcher(pex.getMessage());
113             if (match.matches())
114             {
115                lineNumber = Integer.parseInt(match.group(1));
116                columnNumber = Integer.parseInt(match.group(2));
117                String restOfMsg = match.group(3);
118                msg = "Lexical error, " + restOfMsg + " at " 
119                  + Log.formatFileString(templateName, lineNumber, columnNumber);
120             }
121           
122             //  ugly, ugly, ugly...
123 
124             if (pex.currentToken != null && pex.currentToken.next != null)
125             {
126                 columnNumber = pex.currentToken.next.beginColumn;
127                 lineNumber = pex.currentToken.next.beginLine;
128             }
129         }
130     }
131 
132     /**
133      * Create a ParseErrorException with the given ParseException.
134      *
135      * @param pex the parsing exception
136      * @since 1.5
137      */
138     public ParseErrorException(VelocityException pex, String templName)
139     {
140         super(pex.getMessage());
141         
142         if (templName != null) templateName = templName;
143 
144         // Don't use a second C'tor, TemplateParseException is a subclass of
145         // ParseException...
146         if (pex instanceof ExtendedParseException)
147         {
148             ExtendedParseException xpex = (ExtendedParseException) pex;
149 
150             columnNumber = xpex.getColumnNumber();
151             lineNumber = xpex.getLineNumber();
152             templateName = xpex.getTemplateName();
153         }
154         else if (pex.getWrappedThrowable() instanceof ParseException)
155         {
156             ParseException pex2 = (ParseException) pex.getWrappedThrowable();
157 
158             if (pex2.currentToken != null && pex2.currentToken.next != null)
159             {
160                 columnNumber = pex2.currentToken.next.beginColumn;
161                 lineNumber = pex2.currentToken.next.beginLine;
162             }
163         }
164     }
165 
166 
167     /**
168      * Create a ParseErrorRuntimeException with the given message and info
169      * 
170      * @param exceptionMessage the error exception message
171      * @param info an Info object with the current template info
172      * @since 1.5
173      */
174     public ParseErrorException(String exceptionMessage, Info info)
175     {
176         super(exceptionMessage);
177         columnNumber = info.getColumn();
178         lineNumber = info.getLine();
179         templateName = info.getTemplateName();        
180     }    
181 
182     /**
183      * Create a ParseErrorRuntimeException with the given message and info
184      * 
185      * @param exceptionMessage the error exception message
186      * @param info an Info object with the current template info
187      * @param invalidSyntax the invalid syntax or reference triggering this exception
188      * @since 1.5
189      */
190     public ParseErrorException(String exceptionMessage, 
191             Info info, String invalidSyntax)
192     {
193         super(exceptionMessage);
194         columnNumber = info.getColumn();
195         lineNumber = info.getLine();
196         templateName = info.getTemplateName();  
197         this.invalidSyntax = invalidSyntax;       
198     }    
199 
200 
201     /**
202      * Return the column number of the parsing error, or -1 if not defined.
203      *
204      * @return column number of the parsing error, or -1 if not defined
205      * @since 1.5
206      */
207     public int getColumnNumber()
208     {
209         return columnNumber;
210     }
211 
212     /**
213      * Return the line number of the parsing error, or -1 if not defined.
214      *
215      * @return line number of the parsing error, or -1 if not defined
216      * @since 1.5
217      */
218     public int getLineNumber()
219     {
220         return lineNumber;
221     }
222 
223     /**
224      * Return the name of the template containing the error, or null if not
225      * defined.
226      *
227      * @return the name of the template containing the parsing error, or null
228      *      if not defined
229      * @since 1.5
230      */
231     public String getTemplateName()
232     {
233         return templateName;
234     }
235 
236     /**
237      * Return the invalid syntax or reference that triggered this error, or null
238      * if not defined.
239      * 
240      * @return Return the invalid syntax or reference that triggered this error, or null
241      * if not defined
242      * @since 1.5
243      */
244     public String getInvalidSyntax()
245     {
246         return invalidSyntax;
247     }
248 
249     /**
250      * Return our custum message if we have one, else return the default message
251      */
252     public String getMessage()
253     {
254       if (msg != null) return msg;
255       return super.getMessage();
256     }
257 }