ELEvaluatorpublic class ELEvaluator extends Object This is the main class for evaluating expression Strings. An
expression String is a String that may contain expressions of the
form ${...}. Multiple expressions may appear in the same
expression String. In such a case, the expression String's value
is computed by concatenating the String values of those evaluated
expressions and any intervening non-expression text, then
converting the resulting String to the expected type using the
PropertyEditor mechanism.
In the special case where the expression String is a single
expression, the value of the expression String is determined by
evaluating the expression, without any intervening conversion to a
String.
The evaluator maintains a cache mapping expression Strings to
their parsed results. For expression Strings containing no
expression elements, it maintains a cache mapping
ExpectedType/ExpressionString to parsed value, so that static
expression Strings won't have to go through a conversion step every
time they are used. All instances of the evaluator share the same
cache. The cache may be bypassed by setting a flag on the
evaluator's constructor.
The evaluator must be passed a VariableResolver in its
constructor. The VariableResolver is used to resolve variable
names encountered in expressions, and can also be used to implement
"implicit objects" that are always present in the namespace.
Different applications will have different policies for variable
lookups and implicit objects - these differences can be
encapsulated in the VariableResolver passed to the evaluator's
constructor.
Most VariableResolvers will need to perform their resolution
against some context. For example, a JSP environment needs a
PageContext to resolve variables. The evaluate() method takes a
generic Object context which is eventually passed to the
VariableResolver - the VariableResolver is responsible for casting
the context to the proper type.
Once an evaluator instance has been constructed, it may be used
multiple times, and may be used by multiple simultaneous Threads.
In other words, an evaluator instance is well-suited for use as a
singleton. |
Fields Summary |
---|
static Map | sCachedExpressionStringsThe mapping from expression String to its parsed form (String,
Expression, or ExpressionString) | static Map | sCachedExpectedTypesThe mapping from ExpectedType to Maps mapping literal String to
parsed value | static Logger | sLoggerThe static Logger | VariableResolver | mResolverThe VariableResolver | boolean | mBypassCacheFlag if the cache should be bypassed |
Constructors Summary |
---|
public ELEvaluator(VariableResolver pResolver)Constructor
//-------------------------------------
mResolver = pResolver;
| public ELEvaluator(VariableResolver pResolver, boolean pBypassCache)Constructor
mResolver = pResolver;
mBypassCache = pBypassCache;
|
Methods Summary |
---|
static java.lang.String | addEscapes(java.lang.String str)Used to convert raw characters to their escaped version when
these raw version cannot be used as part of an ASCII string
literal.
StringBuffer retval = new StringBuffer ();
char ch;
for (int i = 0; i < str.length (); i++) {
switch (str.charAt (i)) {
case 0 :
continue;
case '\b":
retval.append ("\\b");
continue;
case '\t":
retval.append ("\\t");
continue;
case '\n":
retval.append ("\\n");
continue;
case '\f":
retval.append ("\\f");
continue;
case '\r":
retval.append ("\\r");
continue;
default:
if ((ch = str.charAt (i)) < 0x20 || ch > 0x7e) {
String s = "0000" + Integer.toString (ch, 16);
retval.append ("\\u" + s.substring (s.length () - 4, s.length ()));
}
else {
retval.append (ch);
}
continue;
}
}
return retval.toString ();
| java.lang.Object | convertStaticValueToExpectedType(java.lang.String pValue, java.lang.Class pExpectedType, Logger pLogger)Converts the given String, specified as a static expression
string, to the given expected type. The conversion is cached.
// See if the value is already of the expected type
if (pExpectedType == String.class ||
pExpectedType == Object.class) {
return pValue;
}
// Find the cached value
Map valueByString = getOrCreateExpectedTypeMap (pExpectedType);
if (!mBypassCache &&
valueByString.containsKey (pValue)) {
return valueByString.get (pValue);
}
else {
// Convert from a String
Object ret = Coercions.coerce (pValue, pExpectedType, pLogger);
valueByString.put (pValue, ret);
return ret;
}
| java.lang.Object | convertToExpectedType(java.lang.Object pValue, java.lang.Class pExpectedType, Logger pLogger)Converts the given value to the specified expected type.
return Coercions.coerce (pValue,
pExpectedType,
pLogger);
| public java.lang.Object | evaluate(java.lang.String pExpressionString, java.lang.Object pContext, java.lang.Class pExpectedType, java.util.Map functions, java.lang.String defaultPrefix)Evaluates the given expression String
return evaluate (pExpressionString,
pContext,
pExpectedType,
functions,
defaultPrefix,
sLogger);
| java.lang.Object | evaluate(java.lang.String pExpressionString, java.lang.Object pContext, java.lang.Class pExpectedType, java.util.Map functions, java.lang.String defaultPrefix, Logger pLogger)Evaluates the given expression string
// Check for null expression strings
if (pExpressionString == null) {
throw new ELException
(Constants.NULL_EXPRESSION_STRING);
}
// Get the parsed version of the expression string
Object parsedValue = parseExpressionString (pExpressionString);
// Evaluate differently based on the parsed type
if (parsedValue instanceof String) {
// Convert the String, and cache the conversion
String strValue = (String) parsedValue;
return convertStaticValueToExpectedType (strValue,
pExpectedType,
pLogger);
}
else if (parsedValue instanceof Expression) {
// Evaluate the expression and convert
Object value =
((Expression) parsedValue).evaluate (pContext,
mResolver,
functions,
defaultPrefix,
pLogger);
return convertToExpectedType (value,
pExpectedType,
pLogger);
}
else if (parsedValue instanceof ExpressionString) {
// Evaluate the expression/string list and convert
String strValue =
((ExpressionString) parsedValue).evaluate (pContext,
mResolver,
functions,
defaultPrefix,
pLogger);
return convertToExpectedType (strValue,
pExpectedType,
pLogger);
}
else {
// This should never be reached
return null;
}
| static java.lang.String | formatParseException(java.lang.String pExpressionString, org.apache.taglibs.standard.lang.jstl.parser.ParseException pExc)Formats a ParseException into an error message suitable for
displaying on a web page
// Generate the String of expected tokens
StringBuffer expectedBuf = new StringBuffer ();
int maxSize = 0;
boolean printedOne = false;
if (pExc.expectedTokenSequences == null)
return pExc.toString();
for (int i = 0; i < pExc.expectedTokenSequences.length; i++) {
if (maxSize < pExc.expectedTokenSequences [i].length) {
maxSize = pExc.expectedTokenSequences [i].length;
}
for (int j = 0; j < pExc.expectedTokenSequences [i].length; j++) {
if (printedOne) {
expectedBuf.append (", ");
}
expectedBuf.append
(pExc.tokenImage [pExc.expectedTokenSequences [i] [j]]);
printedOne = true;
}
}
String expected = expectedBuf.toString ();
// Generate the String of encountered tokens
StringBuffer encounteredBuf = new StringBuffer ();
Token tok = pExc.currentToken.next;
for (int i = 0; i < maxSize; i++) {
if (i != 0) encounteredBuf.append (" ");
if (tok.kind == 0) {
encounteredBuf.append (pExc.tokenImage [0]);
break;
}
encounteredBuf.append (addEscapes (tok.image));
tok = tok.next;
}
String encountered = encounteredBuf.toString ();
// Format the error message
return MessageFormat.format
(Constants.PARSE_EXCEPTION,
new Object [] {
expected,
encountered,
});
| static java.util.Map | getOrCreateExpectedTypeMap(java.lang.Class pExpectedType)Creates or returns the Map that maps string literals to parsed
values for the specified expected type.
synchronized (sCachedExpectedTypes) {
Map ret = (Map) sCachedExpectedTypes.get (pExpectedType);
if (ret == null) {
ret = Collections.synchronizedMap (new HashMap ());
sCachedExpectedTypes.put (pExpectedType, ret);
}
return ret;
}
| public java.lang.String | parseAndRender(java.lang.String pExpressionString)Parses the given expression string, then converts it back to a
String in its canonical form. This is used to test parsing.
Object val = parseExpressionString (pExpressionString);
if (val instanceof String) {
return (String) val;
}
else if (val instanceof Expression) {
return "${" + ((Expression) val).getExpressionString () + "}";
}
else if (val instanceof ExpressionString) {
return ((ExpressionString) val).getExpressionString ();
}
else {
return "";
}
| public java.lang.Object | parseExpressionString(java.lang.String pExpressionString)Gets the parsed form of the given expression string. If the
parsed form is cached (and caching is not bypassed), return the
cached form, otherwise parse and cache the value. Returns either
a String, Expression, or ExpressionString.
// See if it's an empty String
if (pExpressionString.length () == 0) {
return "";
}
// See if it's in the cache
Object ret =
mBypassCache ?
null :
sCachedExpressionStrings.get (pExpressionString);
if (ret == null) {
// Parse the expression
Reader r = new StringReader (pExpressionString);
ELParser parser = new ELParser (r);
try {
ret = parser.ExpressionString ();
sCachedExpressionStrings.put (pExpressionString, ret);
}
catch (ParseException exc) {
throw new ELException
(formatParseException (pExpressionString,
exc));
}
catch (TokenMgrError exc) {
// Note - this should never be reached, since the parser is
// constructed to tokenize any input (illegal inputs get
// parsed to <BADLY_ESCAPED_STRING_LITERAL> or
// <ILLEGAL_CHARACTER>
throw new ELException (exc.getMessage ());
}
}
return ret;
|
|