![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.commons.jexl2.JexlException Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons-jexl Show documentation
Show all versions of commons-jexl Show documentation
The Commons Jexl library is an implementation of the JSTL Expression Language with extensions.
/*
* 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.
*/
package org.apache.commons.jexl2;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
import org.apache.commons.jexl2.parser.JexlNode;
import org.apache.commons.jexl2.parser.ParseException;
import org.apache.commons.jexl2.parser.TokenMgrError;
/**
* Wraps any error that might occur during interpretation of a script or expression.
* @since 2.0
*/
public class JexlException extends RuntimeException {
/** The point of origin for this exception. */
protected final transient JexlNode mark;
/** The debug info. */
protected final transient JexlInfo info;
/** A marker to use in NPEs stating a null operand error. */
public static final String NULL_OPERAND = "jexl.null";
/** Minimum number of characters around exception location. */
private static final int MIN_EXCHARLOC = 5;
/** Maximum number of characters around exception location. */
private static final int MAX_EXCHARLOC = 10;
/**
* Creates a new JexlException.
* @param node the node causing the error
* @param msg the error message
*/
public JexlException(JexlNode node, String msg) {
super(msg);
mark = node;
info = node != null ? node.debugInfo() : null;
}
/**
* Creates a new JexlException.
* @param node the node causing the error
* @param msg the error message
* @param cause the exception causing the error
*/
public JexlException(JexlNode node, String msg, Throwable cause) {
super(msg, unwrap(cause));
mark = node;
info = node != null ? node.debugInfo() : null;
}
/**
* Creates a new JexlException.
* @param dbg the debugging information associated
* @param msg the error message
*/
public JexlException(JexlInfo dbg, String msg) {
super(msg);
mark = null;
info = dbg;
}
/**
* Creates a new JexlException.
* @param dbg the debugging information associated
* @param msg the error message
* @param cause the exception causing the error
*/
public JexlException(JexlInfo dbg, String msg, Throwable cause) {
super(msg, unwrap(cause));
mark = null;
info = dbg;
}
/**
* Unwraps the cause of a throwable due to reflection.
* @param xthrow the throwable
* @return the cause
*/
private static Throwable unwrap(Throwable xthrow) {
if (xthrow instanceof InvocationTargetException) {
return ((InvocationTargetException) xthrow).getTargetException();
} else if (xthrow instanceof UndeclaredThrowableException) {
return ((UndeclaredThrowableException) xthrow).getUndeclaredThrowable();
} else {
return xthrow;
}
}
/**
* Accesses detailed message.
* @return the message
* @since 2.1
*/
protected String detailedMessage() {
return super.getMessage();
}
/**
* Formats an error message from the parser.
* @param prefix the prefix to the message
* @param expr the expression in error
* @return the formatted message
* @since 2.1
*/
protected String parserError(String prefix, String expr) {
int begin = info.debugInfo().getColumn();
int end = begin + MIN_EXCHARLOC;
begin -= MIN_EXCHARLOC;
if (begin < 0) {
end += MIN_EXCHARLOC;
begin = 0;
}
int length = expr.length();
if (length < MAX_EXCHARLOC) {
return prefix + " error in '" + expr + "'";
} else {
return prefix + " error near '... "
+ expr.substring(begin, end > length ? length : end) + " ...'";
}
}
/**
* Thrown when tokenization fails.
* @since 2.1
*/
public static class Tokenization extends JexlException {
/**
* Creates a new Tokenization exception instance.
* @param node the location info
* @param expr the expression
* @param cause the javacc cause
*/
public Tokenization(JexlInfo node, CharSequence expr, TokenMgrError cause) {
super(merge(node, cause), expr.toString(), cause);
}
/**
* Merge the node info and the cause info to obtain best possible location.
* @param node the node
* @param cause the cause
* @return the info to use
*/
private static DebugInfo merge(JexlInfo node, TokenMgrError cause) {
DebugInfo dbgn = node != null ? node.debugInfo() : null;
if (cause == null) {
return dbgn;
} else if (dbgn == null) {
return new DebugInfo("", cause.getLine(), cause.getColumn());
} else {
return new DebugInfo(dbgn.getName(), cause.getLine(), cause.getColumn());
}
}
/**
* @return the expression
*/
public String getExpression() {
return super.detailedMessage();
}
@Override
protected String detailedMessage() {
return parserError("tokenization", getExpression());
}
}
/**
* Thrown when parsing fails.
* @since 2.1
*/
public static class Parsing extends JexlException {
/**
* Creates a new Variable exception instance.
* @param node the offending ASTnode
* @param expr the offending source
* @param cause the javacc cause
*/
public Parsing(JexlInfo node, CharSequence expr, ParseException cause) {
super(merge(node, cause), expr.toString(), cause);
}
/**
* Merge the node info and the cause info to obtain best possible location.
* @param node the node
* @param cause the cause
* @return the info to use
*/
private static DebugInfo merge(JexlInfo node, ParseException cause) {
DebugInfo dbgn = node != null ? node.debugInfo() : null;
if (cause == null) {
return dbgn;
} else if (dbgn == null) {
return new DebugInfo("", cause.getLine(), cause.getColumn());
} else {
return new DebugInfo(dbgn.getName(), cause.getLine(), cause.getColumn());
}
}
/**
* @return the expression
*/
public String getExpression() {
return super.detailedMessage();
}
@Override
protected String detailedMessage() {
return parserError("parsing", getExpression());
}
}
/**
* Thrown when a variable is unknown.
* @since 2.1
*/
public static class Variable extends JexlException {
/**
* Creates a new Variable exception instance.
* @param node the offending ASTnode
* @param var the unknown variable
*/
public Variable(JexlNode node, String var) {
super(node, var);
}
/**
* @return the variable name
*/
public String getVariable() {
return super.detailedMessage();
}
@Override
protected String detailedMessage() {
return "undefined variable " + getVariable();
}
}
/**
* Thrown when a property is unknown.
* @since 2.1
*/
public static class Property extends JexlException {
/**
* Creates a new Property exception instance.
* @param node the offending ASTnode
* @param var the unknown variable
*/
public Property(JexlNode node, String var) {
super(node, var);
}
/**
* @return the property name
*/
public String getProperty() {
return super.detailedMessage();
}
@Override
protected String detailedMessage() {
return "inaccessible or unknown property " + getProperty();
}
}
/**
* Thrown when a method or ctor is unknown, ambiguous or inaccessible.
* @since 2.1
*/
public static class Method extends JexlException {
/**
* Creates a new Method exception instance.
* @param node the offending ASTnode
* @param name the unknown method
*/
public Method(JexlNode node, String name) {
super(node, name);
}
/**
* @return the method name
*/
public String getMethod() {
return super.detailedMessage();
}
@Override
protected String detailedMessage() {
return "unknown, ambiguous or inaccessible method " + getMethod();
}
}
/**
* Thrown to return a value.
* @since 2.1
*/
protected static class Return extends JexlException {
/** The returned value. */
private final Object result;
/**
* Creates a new instance of Return.
* @param node the return node
* @param msg the message
* @param value the returned value
*/
protected Return(JexlNode node, String msg, Object value) {
super(node, msg);
this.result = value;
}
/**
* @return the returned value
*/
public Object getValue() {
return result;
}
}
/**
* Thrown to cancel a script execution.
* @since 2.1
*/
protected static class Cancel extends JexlException {
/**
* Creates a new instance of Cancel.
* @param node the node where the interruption was detected
*/
protected Cancel(JexlNode node) {
super(node, "execution cancelled", null);
}
}
/**
* Gets information about the cause of this error.
*
* The returned string represents the outermost expression in error.
* The info parameter, an int[2] optionally provided by the caller, will be filled with the begin/end offset
* characters of the precise error's trigger.
*
* @param offsets character offset interval of the precise node triggering the error
* @return a string representation of the offending expression, the empty string if it could not be determined
*/
public String getInfo(int[] offsets) {
Debugger dbg = new Debugger();
if (dbg.debug(mark)) {
if (offsets != null && offsets.length >= 2) {
offsets[0] = dbg.start();
offsets[1] = dbg.end();
}
return dbg.data();
}
return "";
}
/**
* Detailed info message about this error.
* Format is "debug![begin,end]: string \n msg" where:
* - debug is the debugging information if it exists (@link JexlEngine.setDebug)
* - begin, end are character offsets in the string for the precise location of the error
* - string is the string representation of the offending expression
* - msg is the actual explanation message for this error
* @return this error as a string
*/
@Override
public String getMessage() {
Debugger dbg = new Debugger();
StringBuilder msg = new StringBuilder();
if (info != null) {
msg.append(info.debugString());
}
if (dbg.debug(mark)) {
msg.append("![");
msg.append(dbg.start());
msg.append(",");
msg.append(dbg.end());
msg.append("]: '");
msg.append(dbg.data());
msg.append("'");
}
msg.append(' ');
msg.append(detailedMessage());
Throwable cause = getCause();
if (cause != null && NULL_OPERAND == cause.getMessage()) {
msg.append(" caused by null operand");
}
return msg.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy