From 7678392d85f43c60c93f2a08dcba6aa7ec6102e4 Mon Sep 17 00:00:00 2001 From: memesaregood1 Date: Tue, 21 Feb 2023 22:39:14 +0300 Subject: Implement JEXL parser settings --- src/main/java/org/traccar/config/Keys.java | 95 ++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) (limited to 'src/main/java/org/traccar/config') diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 093f4298c..49af7cfab 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -1299,6 +1299,101 @@ public final class Keys { public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES = new BooleanConfigKey( "processing.computedAttributes.deviceAttributes", List.of(KeyType.CONFIG)); + /** + * Enable annotation constructs processing. + * When disabled, parsing a script/expression using syntactic annotation constructs (@annotation) will throw a parsing exception. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_ANNOTATION = new BooleanConfigKey( + "processing.computedAttributes.parser.annotation", + List.of(KeyType.CONFIG)); + /** + * Enable array references processing. + * When disabled, parsing a script/expression using 'obj[ ref ]' where ref is not a string or integer literal will throw a parsing exception; + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_ARRAY_REFERENCES = new BooleanConfigKey( + "processing.computedAttributes.parser.arrayReferences", + List.of(KeyType.CONFIG)); + /** + * Enable lambda declaration. + * When disabled, parsing a script/expression using syntactic lambda constructs (->,function) will throw a parsing exception. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LAMBDA = new BooleanConfigKey( + "processing.computedAttributes.parser.lambda", + List.of(KeyType.CONFIG)); + /** + * Enable whether redefining local variables is an error. + * When disabled, parsing a script/expression using a local variable or parameter syntax will throw a parsing exception. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LEXICAL = new BooleanConfigKey( + "processing.computedAttributes.parser.lexical", + List.of(KeyType.CONFIG)); + /** + * Enable whether local variables shade global variables outside their scope. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LEXICAL_SHADE = new BooleanConfigKey( + "processing.computedAttributes.parser.lexicalShade", + List.of(KeyType.CONFIG)); + /** + * Enable local variables declaration. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LOCAL_VARIABLES = new BooleanConfigKey( + "processing.computedAttributes.parser.localVariables", + List.of(KeyType.CONFIG)); + /** + * Enable loops processing. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LOOPS = new BooleanConfigKey( + "processing.computedAttributes.parser.loops", + List.of(KeyType.CONFIG)); + /** + * Set whether object method calls are enabled. + * When disabled, parsing a script/expression using 'obj.method()' will throw a parsing exception; + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_METHOD_CALLS = new BooleanConfigKey( + "processing.computedAttributes.parser.method_calls", + List.of(KeyType.CONFIG)); + /** + * Enable new instances creation. + * When disabled, parsing a script/expression using 'new(...)' will throw a parsing exception; using a class as functor will fail. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_NEW_INSTANCE_CREATION = new BooleanConfigKey( + "processing.computedAttributes.parser.newInstanceCreation", + List.of(KeyType.CONFIG)); + /** + * Enable pragma expressions processing. + * When disabled, parsing a script/expression using syntactic pragma constructs (#pragma) will throw a parsing exception. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_PRAGMA = new BooleanConfigKey( + "processing.computedAttributes.parser.pragma", + List.of(KeyType.CONFIG)); + /** + * Enable scripts constructs processing. + * When disabled, parsing a script using syntactic script constructs (statements, ...) will throw a parsing exception. + * Dangerous, as can be used to escalate privileges on the Traccar server. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_SCRIPT_CONSTRUCTS = new BooleanConfigKey( + "processing.computedAttributes.parser.scriptConstructs", + List.of(KeyType.CONFIG)); + /** + * Enable side effect expressions processing. + * When disabled, parsing a script/expression using syntactical constructs modifying variables or members will throw a parsing exception. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_SIDE_EFFECT = new BooleanConfigKey( + "processing.computedAttributes.parser.sideEffect", + List.of(KeyType.CONFIG)); + /** + * Set whether side effect expressions on global variables (aka non-local) are enabled. + * When disabled, parsing a script/expression using syntactical constructs modifying variables including all potentially ant-ish variables will throw a parsing exception. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_SIDE_EFFECT_GLOBAL = new BooleanConfigKey( + "processing.computedAttributes.parser.sideEffectGlobal", + List.of(KeyType.CONFIG)); + /** + * Enable array/map/set literal expressions processing. + */ + public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_STRUCTURED_LITERAL = new BooleanConfigKey( + "processing.computedAttributes.parser.structuredLiteral", + List.of(KeyType.CONFIG)); /** * Boolean flag to enable or disable reverse geocoder. -- cgit v1.2.3 From a41ad7237035b27634cd6eac1a68e3cf1b553be9 Mon Sep 17 00:00:00 2001 From: memesaregood1 Date: Tue, 21 Feb 2023 23:14:35 +0300 Subject: Shorten JEXL features palette --- src/main/java/org/traccar/config/Keys.java | 83 +--------------------- .../traccar/handler/ComputedAttributesHandler.java | 25 +------ 2 files changed, 4 insertions(+), 104 deletions(-) (limited to 'src/main/java/org/traccar/config') diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 49af7cfab..53f0336cc 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -1299,102 +1299,25 @@ public final class Keys { public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES = new BooleanConfigKey( "processing.computedAttributes.deviceAttributes", List.of(KeyType.CONFIG)); - /** - * Enable annotation constructs processing. - * When disabled, parsing a script/expression using syntactic annotation constructs (@annotation) will throw a parsing exception. - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_ANNOTATION = new BooleanConfigKey( - "processing.computedAttributes.parser.annotation", - List.of(KeyType.CONFIG)); - /** - * Enable array references processing. - * When disabled, parsing a script/expression using 'obj[ ref ]' where ref is not a string or integer literal will throw a parsing exception; - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_ARRAY_REFERENCES = new BooleanConfigKey( - "processing.computedAttributes.parser.arrayReferences", - List.of(KeyType.CONFIG)); - /** - * Enable lambda declaration. - * When disabled, parsing a script/expression using syntactic lambda constructs (->,function) will throw a parsing exception. - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LAMBDA = new BooleanConfigKey( - "processing.computedAttributes.parser.lambda", - List.of(KeyType.CONFIG)); - /** - * Enable whether redefining local variables is an error. - * When disabled, parsing a script/expression using a local variable or parameter syntax will throw a parsing exception. - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LEXICAL = new BooleanConfigKey( - "processing.computedAttributes.parser.lexical", - List.of(KeyType.CONFIG)); - /** - * Enable whether local variables shade global variables outside their scope. - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LEXICAL_SHADE = new BooleanConfigKey( - "processing.computedAttributes.parser.lexicalShade", - List.of(KeyType.CONFIG)); /** * Enable local variables declaration. */ public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LOCAL_VARIABLES = new BooleanConfigKey( - "processing.computedAttributes.parser.localVariables", + "processing.computedAttributes.localVariables", List.of(KeyType.CONFIG)); /** * Enable loops processing. */ public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LOOPS = new BooleanConfigKey( - "processing.computedAttributes.parser.loops", - List.of(KeyType.CONFIG)); - /** - * Set whether object method calls are enabled. - * When disabled, parsing a script/expression using 'obj.method()' will throw a parsing exception; - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_METHOD_CALLS = new BooleanConfigKey( - "processing.computedAttributes.parser.method_calls", + "processing.computedAttributes.loops", List.of(KeyType.CONFIG)); /** * Enable new instances creation. * When disabled, parsing a script/expression using 'new(...)' will throw a parsing exception; using a class as functor will fail. */ public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_NEW_INSTANCE_CREATION = new BooleanConfigKey( - "processing.computedAttributes.parser.newInstanceCreation", + "processing.computedAttributes.newInstanceCreation", List.of(KeyType.CONFIG)); - /** - * Enable pragma expressions processing. - * When disabled, parsing a script/expression using syntactic pragma constructs (#pragma) will throw a parsing exception. - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_PRAGMA = new BooleanConfigKey( - "processing.computedAttributes.parser.pragma", - List.of(KeyType.CONFIG)); - /** - * Enable scripts constructs processing. - * When disabled, parsing a script using syntactic script constructs (statements, ...) will throw a parsing exception. - * Dangerous, as can be used to escalate privileges on the Traccar server. - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_SCRIPT_CONSTRUCTS = new BooleanConfigKey( - "processing.computedAttributes.parser.scriptConstructs", - List.of(KeyType.CONFIG)); - /** - * Enable side effect expressions processing. - * When disabled, parsing a script/expression using syntactical constructs modifying variables or members will throw a parsing exception. - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_SIDE_EFFECT = new BooleanConfigKey( - "processing.computedAttributes.parser.sideEffect", - List.of(KeyType.CONFIG)); - /** - * Set whether side effect expressions on global variables (aka non-local) are enabled. - * When disabled, parsing a script/expression using syntactical constructs modifying variables including all potentially ant-ish variables will throw a parsing exception. - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_SIDE_EFFECT_GLOBAL = new BooleanConfigKey( - "processing.computedAttributes.parser.sideEffectGlobal", - List.of(KeyType.CONFIG)); - /** - * Enable array/map/set literal expressions processing. - */ - public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_STRUCTURED_LITERAL = new BooleanConfigKey( - "processing.computedAttributes.parser.structuredLiteral", - List.of(KeyType.CONFIG)); - /** * Boolean flag to enable or disable reverse geocoder. */ diff --git a/src/main/java/org/traccar/handler/ComputedAttributesHandler.java b/src/main/java/org/traccar/handler/ComputedAttributesHandler.java index c3f202fa2..912665630 100644 --- a/src/main/java/org/traccar/handler/ComputedAttributesHandler.java +++ b/src/main/java/org/traccar/handler/ComputedAttributesHandler.java @@ -57,39 +57,16 @@ public class ComputedAttributesHandler extends BaseDataHandler { @Inject public ComputedAttributesHandler(Config config, CacheManager cacheManager) { this.cacheManager = cacheManager; - boolean enableJEXLAnnotation = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_ANNOTATION); - boolean enableJEXLArrayReferences = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_ARRAY_REFERENCES); - boolean enableJEXLLambdas = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LAMBDA); - boolean enableJEXLLexical = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LEXICAL); - boolean enableJEXLLexicalShade = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LEXICAL_SHADE); boolean enableJEXLLocalVariables = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LOCAL_VARIABLES); boolean enableJEXLLoops = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LOOPS); - boolean enableJEXLMethodCalls = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_METHOD_CALLS); boolean enableJEXLNewInstanceCreation = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_NEW_INSTANCE_CREATION); - boolean enableJEXLPragma = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_PRAGMA); - boolean enableJEXLScriptConstructs = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_SCRIPT_CONSTRUCTS); - boolean enableJEXLSideEffect = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_SIDE_EFFECT); - boolean enableJEXLSideEffectGlobal = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_SIDE_EFFECT_GLOBAL); - boolean enableJEXLStructuredLiteral = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_STRUCTURED_LITERAL); JexlSandbox sandbox = new JexlSandbox(false); sandbox.allow("com.safe.Functions"); - boolean enableJEXLRegister = true; JexlFeatures features = new JexlFeatures() - .annotation(enableJEXLAnnotation) - .arrayReferenceExpr(enableJEXLArrayReferences) - .lambda(enableJEXLLambdas) - .lexical(enableJEXLLexical) - .lexicalShade(enableJEXLLexicalShade) .localVar(enableJEXLLocalVariables) .loops(enableJEXLLoops) - .methodCall(enableJEXLMethodCalls) .newInstance(enableJEXLNewInstanceCreation) - .pragma(enableJEXLPragma) - .register(enableJEXLRegister) - .script(enableJEXLScriptConstructs) - .sideEffect(enableJEXLSideEffect) - .sideEffectGlobal(enableJEXLSideEffectGlobal) - .structuredLiteral(enableJEXLStructuredLiteral); + .structuredLiteral(true); engine = new JexlBuilder() .strict(true) .namespaces(Collections.singletonMap("math", Math.class)) -- cgit v1.2.3 From 9deca13ced10ef8a6df164831dd60ed4089a25a6 Mon Sep 17 00:00:00 2001 From: memesaregood1 Date: Wed, 22 Feb 2023 21:43:47 +0300 Subject: lint patch --- src/main/java/org/traccar/config/Keys.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/main/java/org/traccar/config') diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 53f0336cc..6aa41f85b 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -1299,25 +1299,29 @@ public final class Keys { public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES = new BooleanConfigKey( "processing.computedAttributes.deviceAttributes", List.of(KeyType.CONFIG)); + /** * Enable local variables declaration. */ public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LOCAL_VARIABLES = new BooleanConfigKey( "processing.computedAttributes.localVariables", List.of(KeyType.CONFIG)); + /** * Enable loops processing. */ public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LOOPS = new BooleanConfigKey( "processing.computedAttributes.loops", List.of(KeyType.CONFIG)); + /** * Enable new instances creation. - * When disabled, parsing a script/expression using 'new(...)' will throw a parsing exception; using a class as functor will fail. + * When disabled, parsing a script/expression using 'new(...)' will throw a parsing exception; */ public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_NEW_INSTANCE_CREATION = new BooleanConfigKey( "processing.computedAttributes.newInstanceCreation", List.of(KeyType.CONFIG)); + /** * Boolean flag to enable or disable reverse geocoder. */ -- cgit v1.2.3 From 0fe0344a64b142ef4492ff6ad3c1f8590d336ab0 Mon Sep 17 00:00:00 2001 From: memesaregood1 Date: Wed, 22 Feb 2023 22:46:50 +0300 Subject: Alternative features activation way --- src/main/java/org/traccar/config/Keys.java | 8 ++++---- src/main/java/org/traccar/handler/ComputedAttributesHandler.java | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/main/java/org/traccar/config') diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 6aa41f85b..d3bba9ae7 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -1299,21 +1299,21 @@ public final class Keys { public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES = new BooleanConfigKey( "processing.computedAttributes.deviceAttributes", List.of(KeyType.CONFIG)); - + /** * Enable local variables declaration. */ public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LOCAL_VARIABLES = new BooleanConfigKey( "processing.computedAttributes.localVariables", List.of(KeyType.CONFIG)); - + /** * Enable loops processing. */ public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LOOPS = new BooleanConfigKey( "processing.computedAttributes.loops", List.of(KeyType.CONFIG)); - + /** * Enable new instances creation. * When disabled, parsing a script/expression using 'new(...)' will throw a parsing exception; @@ -1321,7 +1321,7 @@ public final class Keys { public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_NEW_INSTANCE_CREATION = new BooleanConfigKey( "processing.computedAttributes.newInstanceCreation", List.of(KeyType.CONFIG)); - + /** * Boolean flag to enable or disable reverse geocoder. */ diff --git a/src/main/java/org/traccar/handler/ComputedAttributesHandler.java b/src/main/java/org/traccar/handler/ComputedAttributesHandler.java index 73b549195..2964d81d7 100644 --- a/src/main/java/org/traccar/handler/ComputedAttributesHandler.java +++ b/src/main/java/org/traccar/handler/ComputedAttributesHandler.java @@ -55,6 +55,8 @@ public class ComputedAttributesHandler extends BaseDataHandler { private final JexlEngine engine; + private final JexlFeatures features; + private final boolean includeDeviceAttributes; @Inject @@ -62,7 +64,7 @@ public class ComputedAttributesHandler extends BaseDataHandler { this.cacheManager = cacheManager; JexlSandbox sandbox = new JexlSandbox(false); sandbox.allow("com.safe.Functions"); - JexlFeatures features = new JexlFeatures() + features = new JexlFeatures() .localVar(config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LOCAL_VARIABLES)) .loops(config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_LOOPS)) .newInstance(config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_NEW_INSTANCE_CREATION)) @@ -71,7 +73,6 @@ public class ComputedAttributesHandler extends BaseDataHandler { .strict(true) .namespaces(Collections.singletonMap("math", Math.class)) .sandbox(sandbox) - .features(features) .create(); includeDeviceAttributes = config.getBoolean(Keys.PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES); } @@ -113,7 +114,7 @@ public class ComputedAttributesHandler extends BaseDataHandler { */ @Deprecated public Object computeAttribute(Attribute attribute, Position position) throws JexlException { - return engine.createExpression(attribute.getExpression()).evaluate(prepareContext(position)); + return engine.createScript(features, engine.createInfo(), attribute.getExpression()).execute(prepareContext(position)); } @Override -- cgit v1.2.3 From 7a8fc065a116af1f944959354495db00459d2199 Mon Sep 17 00:00:00 2001 From: memesaregood1 Date: Thu, 23 Feb 2023 22:07:42 +0300 Subject: Fix lint issues once again --- src/main/java/org/traccar/config/Keys.java | 8 ++++---- src/main/java/org/traccar/handler/ComputedAttributesHandler.java | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src/main/java/org/traccar/config') diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index d3bba9ae7..6aa41f85b 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -1299,21 +1299,21 @@ public final class Keys { public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_DEVICE_ATTRIBUTES = new BooleanConfigKey( "processing.computedAttributes.deviceAttributes", List.of(KeyType.CONFIG)); - + /** * Enable local variables declaration. */ public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LOCAL_VARIABLES = new BooleanConfigKey( "processing.computedAttributes.localVariables", List.of(KeyType.CONFIG)); - + /** * Enable loops processing. */ public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_LOOPS = new BooleanConfigKey( "processing.computedAttributes.loops", List.of(KeyType.CONFIG)); - + /** * Enable new instances creation. * When disabled, parsing a script/expression using 'new(...)' will throw a parsing exception; @@ -1321,7 +1321,7 @@ public final class Keys { public static final ConfigKey PROCESSING_COMPUTED_ATTRIBUTES_NEW_INSTANCE_CREATION = new BooleanConfigKey( "processing.computedAttributes.newInstanceCreation", List.of(KeyType.CONFIG)); - + /** * Boolean flag to enable or disable reverse geocoder. */ diff --git a/src/main/java/org/traccar/handler/ComputedAttributesHandler.java b/src/main/java/org/traccar/handler/ComputedAttributesHandler.java index 0eab509ee..e8a4998e3 100644 --- a/src/main/java/org/traccar/handler/ComputedAttributesHandler.java +++ b/src/main/java/org/traccar/handler/ComputedAttributesHandler.java @@ -115,7 +115,9 @@ public class ComputedAttributesHandler extends BaseDataHandler { */ @Deprecated public Object computeAttribute(Attribute attribute, Position position) throws JexlException { - return engine.createScript(features, engine.createInfo(), attribute.getExpression()).execute(prepareContext(position)); + return engine.createScript(features, + engine.createInfo(), + attribute.getExpression()).execute(prepareContext(position)); } @Override -- cgit v1.2.3