diff options
author | Claude Brisson <cbrisson@apache.org> | 2019-06-12 00:58:53 +0000 |
---|---|---|
committer | Claude Brisson <cbrisson@apache.org> | 2019-06-12 00:58:53 +0000 |
commit | 1bf4b32ffc5f9637285ce7de855460fd00da10b0 (patch) | |
tree | 1c4050072d9d831133ea7d39b9a568d2603d33ed /velocity-engine-core/src/main/java/org/apache/velocity/runtime | |
parent | 9cc0c4e1f55b06cb587432d06e203f5f7c3d6293 (diff) | |
parent | 0c363b9df8654b05c503c6b192e94dfc458482dd (diff) | |
download | apache-velocity-engine-1bf4b32ffc5f9637285ce7de855460fd00da10b0.tar.gz |
[engine][VELOCITY-917] Merge changes from trunk
git-svn-id: https://svn.apache.org/repos/asf/velocity/engine/branches/parser_experiments@1861084 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'velocity-engine-core/src/main/java/org/apache/velocity/runtime')
2 files changed, 77 insertions, 20 deletions
diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java index 0ac45111..89aac7ec 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java @@ -274,6 +274,30 @@ public interface RuntimeConstants extends DeprecatedRuntimeConstants */ String EVENTHANDLER_INVALIDREFERENCES = "event_handler.invalid_references.class"; + /** + * The <code>event_handler.invalid_references.quiet</code> property specifies if invalid quiet references + * (as in <code>$!foo</code>) trigger events (defaults to false). + * {@link org.apache.velocity.app.event.InvalidReferenceEventHandler} implementations to use. + * @since 2.2 + */ + String EVENTHANDLER_INVALIDREFERENCES_QUIET = "event_handler.invalid_references.quiet"; + + /** + * The <code>event_handler.invalid_references.null</code> property specifies if invalid null references + * (aka the value is present in the context or parent object but is null or a method returned null) + * trigger invalid reference events (defaults to false). + * {@link org.apache.velocity.app.event.InvalidReferenceEventHandler} implementations to use. + * @since 2.2 + */ + String EVENTHANDLER_INVALIDREFERENCES_NULL = "event_handler.invalid_references.null"; + + /** + * The <code>event_handler.invalid_references.tested</code> property specifies if invalid tested references + * (as in <code>#if($foo)</code> ) trigger invalid reference events (defaults to false). + * {@link org.apache.velocity.app.event.InvalidReferenceEventHandler} implementations to use. + * @since 2.2 + */ + String EVENTHANDLER_INVALIDREFERENCES_TESTED = "event_handler.invalid_references.tested"; /* * ---------------------------------------------------------------------- diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java index 238336bc..128cb9fa 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTReference.java @@ -102,6 +102,25 @@ public class ASTReference extends SimpleNode private int numChildren = 0; + /** + * Whether to trigger an event for invalid quiet references + * @since 2.2 + */ + private boolean warnInvalidQuietReferences = false; + + /** + * Whether to trigger an event for invalid null references, that is when a value + * is present in the context or parent object but is null + * @since 2.2 + */ + private boolean warnInvalidNullReferences = false; + + /** + * Whether to trigger an event for invalid tested references - as in #if($foo) + * @since 2.2 + */ + private boolean warnInvalidTestedReferences = false; + protected Info uberInfo; /** @@ -196,6 +215,16 @@ public class ASTReference extends SimpleNode checkEmpty = rsvc.getBoolean(RuntimeConstants.CHECK_EMPTY_OBJECTS, true); + /* invalid references special cases */ + + warnInvalidQuietReferences = + rsvc.getBoolean(RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES_QUIET, false); + warnInvalidNullReferences = + rsvc.getBoolean(RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES_NULL, false); + warnInvalidTestedReferences = + rsvc.getBoolean(RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES_TESTED, false); + + /** * In the case we are referencing a variable with #if($foo) or * #if( ! $foo) then we allow variables to be undefined and we @@ -272,25 +301,30 @@ public class ASTReference extends SimpleNode Object result = getRootVariableValue(context); + /* a reference which has been provided an alternate value + * is *knowingly* potentially null and should be accepted + * in strict mode (except if the alternate value is null) + */ + if (astAlternateValue != null && (result == null || !DuckType.asBoolean(result, false))) + { + result = astAlternateValue.value(context); + } + if (result == null && !strictRef) { /* * do not trigger an invalid reference if the reference is present, but with a null value * don't either for a quiet reference or inside an #if/#elseif evaluation context */ - if (referenceType != QUIET_REFERENCE && - (numChildren > 0 || - !context.containsKey(rootString) && !onlyTestingReference)) + if ((referenceType != QUIET_REFERENCE || warnInvalidQuietReferences) && + (numChildren > 0 || + (!context.containsKey(rootString) || warnInvalidNullReferences) && + (!onlyTestingReference || warnInvalidTestedReferences))) { result = EventHandlerUtil.invalidGetMethod(rsvc, context, rsvc.dollar() + rootString, null, null, uberInfo); } - if (result == null && astAlternateValue != null) - { - result = astAlternateValue.value(context); - } - return result; } @@ -311,6 +345,7 @@ public class ASTReference extends SimpleNode { Object previousResult = result; int failedChild = -1; + for (int i = 0; i < numChildren; i++) { if (strictRef && result == null) @@ -327,6 +362,10 @@ public class ASTReference extends SimpleNode } previousResult = result; result = jjtGetChild(i).execute(result,context); + if (astAlternateValue != null && (result == null || !DuckType.asBoolean(result, checkEmpty))) + { + result = astAlternateValue.value(context); + } if (result == null && !strictRef) // If strict and null then well catch this // next time through the loop { @@ -344,7 +383,9 @@ public class ASTReference extends SimpleNode * don't either for a quiet reference, * or inside an #if/#elseif evaluation context when there's no child */ - if (!context.containsKey(rootString) && referenceType != QUIET_REFERENCE && (!onlyTestingReference || numChildren > 0)) + if ((!context.containsKey(rootString) || warnInvalidNullReferences) && + (referenceType != QUIET_REFERENCE || warnInvalidQuietReferences) && + (!onlyTestingReference || warnInvalidTestedReferences || numChildren > 0)) { result = EventHandlerUtil.invalidGetMethod(rsvc, context, rsvc.dollar() + rootString, previousResult, null, uberInfo); @@ -357,9 +398,9 @@ public class ASTReference extends SimpleNode // (it means the getter has been called and returned null) // do not either for a quiet reference or if the *last* child failed while testing the reference Object getter = context.icacheGet(child); - if (getter == null && - referenceType != QUIET_REFERENCE && - (!onlyTestingReference || failedChild < numChildren - 1)) + if ((getter == null || warnInvalidNullReferences) && + (referenceType != QUIET_REFERENCE || warnInvalidQuietReferences) && + (!onlyTestingReference || warnInvalidTestedReferences || failedChild < numChildren - 1)) { StringBuilder name = new StringBuilder(String.valueOf(rsvc.dollar())).append(rootString); for (int i = 0; i <= failedChild; i++) @@ -391,14 +432,6 @@ public class ASTReference extends SimpleNode } } - /* - * Time to try the alternate value if needed - */ - if (astAlternateValue != null && (result == null || !DuckType.asBoolean(result, checkEmpty))) - { - result = astAlternateValue.value(context); - } - return result; } catch(MethodInvocationException mie) |