package org.apache.velocity.exception; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.velocity.runtime.log.Log; import org.apache.velocity.runtime.parser.ParseException; import org.apache.velocity.util.introspection.Info; /** * Application-level exception thrown when a resource of any type * has a syntax or other error which prevents it from being parsed. * <br> * When this resource is thrown, a best effort will be made to have * useful information in the exception's message. For complete * information, consult the runtime log. * * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> * @author <a href="hps@intermeta.de">Henning P. Schmiedehausen</a> * @version $Id: ParseErrorException.java 736638 2009-01-22 13:42:52Z byron $ */ public class ParseErrorException extends VelocityException { /** * Version Id for serializable */ private static final long serialVersionUID = -6665197935086306472L; /** * The column number of the parsing error, or -1 if not defined. */ private int columnNumber = -1; /** * The line number of the parsing error, or -1 if not defined. */ private int lineNumber = -1; /** * The name of the template containing the error, or null if not defined. */ private String templateName = "*unset*"; /** * If applicable, contains the invalid syntax or reference that triggered this exception */ private String invalidSyntax; /** * If we modify the message, then we set this */ private String msg = null; /** * Create a ParseErrorException with the given message. * * @param exceptionMessage the error exception message */ public ParseErrorException(String exceptionMessage) { super(exceptionMessage); } private static final Pattern lexError = Pattern.compile("Lexical error.*TokenMgrError.*line (\\d+),.*column (\\d+)\\.(.*)"); /** * Create a ParseErrorException with the given ParseException. * * @param pex the parsing exception * @since 1.5 */ public ParseErrorException(ParseException pex, String templName) { super(pex.getMessage()); if (templName != null) templateName = templName; // Don't use a second C'tor, TemplateParseException is a subclass of // ParseException... if (pex instanceof ExtendedParseException) { ExtendedParseException xpex = (ExtendedParseException) pex; columnNumber = xpex.getColumnNumber(); lineNumber = xpex.getLineNumber(); templateName = xpex.getTemplateName(); } else { // We get here if the the Parser has thrown an exception. Unfortunately, // the error message created is hard coded by javacc, so here we alter // the error message, so that it is in our standard format. Matcher match = lexError.matcher(pex.getMessage()); if (match.matches()) { lineNumber = Integer.parseInt(match.group(1)); columnNumber = Integer.parseInt(match.group(2)); String restOfMsg = match.group(3); msg = "Lexical error, " + restOfMsg + " at " + Log.formatFileString(templateName, lineNumber, columnNumber); } // ugly, ugly, ugly... if (pex.currentToken != null && pex.currentToken.next != null) { columnNumber = pex.currentToken.next.beginColumn; lineNumber = pex.currentToken.next.beginLine; } } } /** * Create a ParseErrorException with the given ParseException. * * @param pex the parsing exception * @since 1.5 */ public ParseErrorException(VelocityException pex, String templName) { super(pex.getMessage()); if (templName != null) templateName = templName; // Don't use a second C'tor, TemplateParseException is a subclass of // ParseException... if (pex instanceof ExtendedParseException) { ExtendedParseException xpex = (ExtendedParseException) pex; columnNumber = xpex.getColumnNumber(); lineNumber = xpex.getLineNumber(); templateName = xpex.getTemplateName(); } else if (pex.getWrappedThrowable() instanceof ParseException) { ParseException pex2 = (ParseException) pex.getWrappedThrowable(); if (pex2.currentToken != null && pex2.currentToken.next != null) { columnNumber = pex2.currentToken.next.beginColumn; lineNumber = pex2.currentToken.next.beginLine; } } } /** * Create a ParseErrorRuntimeException with the given message and info * * @param exceptionMessage the error exception message * @param info an Info object with the current template info * @since 1.5 */ public ParseErrorException(String exceptionMessage, Info info) { super(exceptionMessage); columnNumber = info.getColumn(); lineNumber = info.getLine(); templateName = info.getTemplateName(); } /** * Create a ParseErrorRuntimeException with the given message and info * * @param exceptionMessage the error exception message * @param info an Info object with the current template info * @param invalidSyntax the invalid syntax or reference triggering this exception * @since 1.5 */ public ParseErrorException(String exceptionMessage, Info info, String invalidSyntax) { super(exceptionMessage); columnNumber = info.getColumn(); lineNumber = info.getLine(); templateName = info.getTemplateName(); this.invalidSyntax = invalidSyntax; } /** * Return the column number of the parsing error, or -1 if not defined. * * @return column number of the parsing error, or -1 if not defined * @since 1.5 */ public int getColumnNumber() { return columnNumber; } /** * Return the line number of the parsing error, or -1 if not defined. * * @return line number of the parsing error, or -1 if not defined * @since 1.5 */ public int getLineNumber() { return lineNumber; } /** * Return the name of the template containing the error, or null if not * defined. * * @return the name of the template containing the parsing error, or null * if not defined * @since 1.5 */ public String getTemplateName() { return templateName; } /** * Return the invalid syntax or reference that triggered this error, or null * if not defined. * * @return Return the invalid syntax or reference that triggered this error, or null * if not defined * @since 1.5 */ public String getInvalidSyntax() { return invalidSyntax; } /** * Return our custum message if we have one, else return the default message */ public String getMessage() { if (msg != null) return msg; return super.getMessage(); } }