1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.jexl3; 19 20 import java.util.concurrent.Callable; 21 import java.util.concurrent.atomic.AtomicBoolean; 22 23 /** 24 * Manages variables which can be referenced in a JEXL expression. 25 * 26 * <p>JEXL variable names in their simplest form are 'java-like' identifiers. 27 * JEXL also considers 'ant' inspired variables expressions as valid. 28 * For instance, the expression 'x.y.z' is an 'antish' variable and will be resolved as a whole by the context, 29 * i.e. using the key "x.y.z". This proves to be useful to solve "fully qualified class names".</p> 30 * 31 * <p>The interpreter variable resolution algorithm will try the different sequences of identifiers till it finds 32 * one that exists in the context; if "x" is an object known in the context (JexlContext.has("x") returns true), 33 * "x.y" will <em>not</em> be looked up in the context but will most likely refer to "x.getY()".</p> 34 * 35 * <p>Note that JEXL may use '$jexl' and '$ujexl' variables for internal purpose; setting or getting those 36 * variables may lead to unexpected results unless specified otherwise.</p> 37 * 38 * @since 1.0 39 */ 40 public interface JexlContext { 41 42 /** 43 * A marker interface of the JexlContext that processes annotations. 44 * It is used by the interpreter during evaluation to execute annotation evaluations. 45 * <p>If the JexlContext is not an instance of an AnnotationProcessor, encountering an annotation will generate 46 * an error or a warning depending on the engine strictness. 47 * @since 3.1 48 */ 49 interface AnnotationProcessor { 50 /** 51 * Processes an annotation. 52 * <p>All annotations are processed through this method; the statement 'call' is to be performed within 53 * the processAnnotation method. The implementation <em>must</em> perform the call explicitly. 54 * <p>The arguments and the statement <em>must not</em> be referenced or cached for longer than the duration 55 * of the processAnnotation call. 56 * 57 * @param name the annotation name 58 * @param args the arguments of the annotation, evaluated as arguments of this call 59 * @param statement the statement that was annotated; the processor should invoke this statement 'call' method 60 * @return the result of statement.call() 61 * @throws Exception if annotation processing fails 62 */ 63 Object processAnnotation(String name, Object[] args, Callable<Object> statement) throws Exception; 64 } 65 66 /** 67 * A marker interface of the JexlContext sharing a cancelling flag. 68 * <p>A script running in a thread can thus be notified through this reference 69 * of its cancellation through the context. It uses the same interpreter logic 70 * that reacts to cancellation and is an alternative to using callable() and/or 71 * interrupting script interpreter threads. 72 * @since 3.2 73 */ 74 interface CancellationHandle { 75 /** 76 * @return a cancelable boolean used by the interpreter 77 */ 78 AtomicBoolean getCancellation(); 79 } 80 81 /** 82 * A marker interface that solves a simple class name into a fully-qualified one. 83 * @since 3.3 84 */ 85 interface ClassNameResolver { 86 /** 87 * Resolves a class name. 88 * @param name the simple class name 89 * @return the fully qualified class name 90 */ 91 String resolveClassName(String name); 92 } 93 94 /** 95 * A marker interface of the JexlContext that processes module definitions. 96 * It is used by the interpreter during evaluation of the pragma module definitions. 97 * @since 3.3 98 */ 99 interface ModuleProcessor { 100 /** 101 * Defines a module. 102 * The module name will be the namespace mapped to the object returned by the evaluation 103 * of its body. 104 * @param engine the engine evaluating this module pragma 105 * @param info the info at the pragma location 106 * @param name the module name 107 * @param body the module definition which can be its location or source 108 * @return the module object 109 */ 110 Object processModule(JexlEngine engine, JexlInfo info, String name, String body); 111 } 112 113 /** 114 * A marker interface of the JexlContext, NamespaceFunctor allows creating an instance 115 * to delegate namespace methods calls to. 116 * 117 * <p>The functor is created once during the lifetime of a script evaluation.</p> 118 */ 119 interface NamespaceFunctor { 120 /** 121 * Creates the functor object that will be used instead of the namespace. 122 * @param context the context 123 * @return the namespace functor instance 124 */ 125 Object createFunctor(JexlContext context); 126 } 127 128 /** 129 * A marker interface of the JexlContext that declares how to resolve a namespace from its name; 130 * it is used by the interpreter during evaluation. 131 * 132 * <p>In JEXL, a namespace is an object that serves the purpose of encapsulating functions; for instance, 133 * the "math" namespace would be the proper object to expose functions like "log(...)", "sinus(...)", etc.</p> 134 * 135 * In expressions like "ns:function(...)", the resolver is called with resolveNamespace("ns"). 136 * 137 * <p>JEXL itself reserves 'jexl' and 'ujexl' as namespaces for internal purpose; resolving those may lead to 138 * unexpected results.</p> 139 * 140 * @since 3.0 141 */ 142 interface NamespaceResolver { 143 144 /** 145 * Resolves a namespace by its name. 146 * @param name the name 147 * @return the namespace object 148 */ 149 Object resolveNamespace(String name); 150 } 151 152 /** 153 * A marker interface of the JexlContext that exposes runtime evaluation options. 154 * @since 3.2 155 */ 156 interface OptionsHandle { 157 /** 158 * Retrieves the current set of options though the context. 159 * <p> 160 * This method will be called once at beginning of evaluation and an interpreter private copy 161 * of the context handled JexlOptions instance used for the duration of the execution; 162 * the context handled JexlOptions instance being only used as the source of that copy, 163 * it can safely alter its boolean flags during execution with no effect, avoiding any behavior ambiguity. 164 * @return the engine options 165 */ 166 JexlOptions getEngineOptions(); 167 } 168 169 /** 170 * A marker interface of the JexlContext that processes pragmas. 171 * It is called by the engine before interpreter creation; as a marker of 172 * JexlContext, it is expected to have access and interact with the context 173 * instance. 174 * @since 3.2 175 */ 176 interface PragmaProcessor { 177 /** 178 * Process one pragma. 179 * @param opts the current evaluator options 180 * @param key the key 181 * @param value the value 182 * @since 3.3 183 */ 184 default void processPragma(final JexlOptions opts, final String key, final Object value) { 185 processPragma(key, value); 186 } 187 188 /** 189 * Process one pragma. 190 * <p>Never called in 3.3, must be implemented for 3.2 binary compatibility reasons.</p> 191 * <p>Typical implementation in 3.3:</p> 192 * <code> 193 * @Override 194 * public void processPragma(String key, Object value) { 195 * processPragma(null, key, value); 196 * } 197 * </code> 198 * @param key the key 199 * @param value the value 200 * @deprecated 3.3 201 */ 202 @Deprecated 203 void processPragma(String key, Object value); 204 } 205 206 /** 207 * A marker interface of the JexlContext that indicates the interpreter to put this context 208 * in the JexlEngine thread local context instance during evaluation. 209 * This allows user functions or methods to access the context during a call. 210 * Note that the usual caveats wrt using thread local apply (caching/leaking references, etc.); in particular, 211 * keeping a reference to such a context is to be considered with great care and caution. 212 * It should also be noted that sharing such a context between threads should implicate synchronizing variable 213 * accessing the implementation class. 214 * 215 * @see JexlEngine#setThreadContext(JexlContext.ThreadLocal) 216 * @see JexlEngine#getThreadContext() 217 */ 218 interface ThreadLocal extends JexlContext { 219 // no specific method 220 } 221 222 /** 223 * Gets the value of a variable. 224 * 225 * @param name the variable's name 226 * @return the value 227 */ 228 Object get(String name); 229 230 /** 231 * Checks whether a variable is defined in this context. 232 * 233 * <p>A variable may be defined with a null value; this method checks whether the 234 * value is null or if the variable is undefined.</p> 235 * 236 * @param name the variable's name 237 * @return true if it exists, false otherwise 238 */ 239 boolean has(String name); 240 241 /** 242 * Sets the value of a variable. 243 * 244 * @param name the variable's name 245 * @param value the variable's value 246 */ 247 void set(String name, Object value); 248 }