View Javadoc
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    *      https://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  package org.apache.commons.jexl3.internal;
18  
19  import org.apache.commons.jexl3.JexlBuilder;
20  import org.apache.commons.jexl3.JexlContext;
21  import org.apache.commons.jexl3.JexlOptions;
22  import org.apache.commons.jexl3.parser.ASTArrayAccess;
23  import org.apache.commons.jexl3.parser.ASTAssignment;
24  import org.apache.commons.jexl3.parser.ASTEQNode;
25  import org.apache.commons.jexl3.parser.ASTIdentifier;
26  import org.apache.commons.jexl3.parser.ASTNENode;
27  import org.apache.commons.jexl3.parser.ASTNullpNode;
28  import org.apache.commons.jexl3.parser.ASTReference;
29  import org.apache.commons.jexl3.parser.ASTTernaryNode;
30  import org.apache.commons.jexl3.parser.JexlNode;
31  
32  /**
33   * An Engine that behaves like JEXL 3.2, bugs included.
34   * @deprecated 3.6.1, use Engine with JexlOptions instead.
35   */
36  @Deprecated
37  public class Engine32 extends Engine {
38      /**
39       * Static delegation of getVariable.
40       * @param ii the interpreter
41       * @param frame the frame
42       * @param block the scope
43       * @param identifier the variable identifier
44       * @return the variable value
45       */
46      static Object getVariable(final Interpreter ii, final Frame frame, final LexicalScope block, final ASTIdentifier identifier) {
47          final int symbol = identifier.getSymbol();
48          // if we have a symbol, we have a scope thus a frame
49          if ((ii.options.isLexicalShade() || identifier.isLexical()) && identifier.isShaded()) {
50              return ii.undefinedVariable(identifier, identifier.getName());
51          }
52          if (symbol >= 0 && frame.has(symbol)) {
53              final Object value = frame.get(symbol);
54              if (value != Scope.UNDEFINED) {
55                  return value;
56              }
57          }
58          final String name = identifier.getName();
59          final Object value = ii.context.get(name);
60          if (value == null && !ii.context.has(name)) {
61              final boolean ignore = ii.isSafe()
62                      && (symbol >= 0
63                      || identifier.jjtGetParent() instanceof ASTAssignment)
64                      || identifier.jjtGetParent() instanceof ASTReference;
65              if (!ignore) {
66                  return ii.unsolvableVariable(identifier, name, true); // undefined
67              }
68          }
69          return value;
70      }
71  
72      /**
73       * Static delegation of isTernaryProtected.
74       * @param ii the interpreter (unused)
75       * @param startNode the node
76       * @return true if node is navigation-safe, false otherwise
77       */
78      static boolean isTernaryProtected(final Interpreter ii, final JexlNode startNode) {
79          JexlNode node = startNode;
80          for (JexlNode walk = node.jjtGetParent(); walk != null; walk = walk.jjtGetParent()) {
81              // protect only the condition part of the ternary
82              if (walk instanceof ASTTernaryNode
83                      || walk instanceof ASTNullpNode
84                      || walk instanceof ASTEQNode
85                      || walk instanceof ASTNENode) {
86                  return node == walk.jjtGetChild(0);
87              }
88              if (!(walk instanceof ASTReference || walk instanceof ASTArrayAccess)) {
89                  break;
90              }
91              node = walk;
92          }
93          return false;
94      }
95  
96      public Engine32() {
97      }
98  
99      public Engine32(final JexlBuilder conf) {
100         super(conf);
101     }
102 
103     @Override
104     protected Interpreter createInterpreter(final JexlContext context, final Frame frame, final JexlOptions opts) {
105         return new Interpreter(this, opts, context, frame) {
106             @Override
107             protected Object getVariable(final Frame frame, final LexicalScope block, final ASTIdentifier identifier) {
108                 return Engine32.getVariable(this, frame, block, identifier);
109             }
110 
111             @Override
112             protected boolean isStrictOperand(final JexlNode node) {
113                 return false;
114             }
115 
116             @Override
117             protected boolean isTernaryProtected(final JexlNode node) {
118                 return Engine32.isTernaryProtected(this, node);
119             }
120         };
121     }
122 
123     @Override
124     protected Interpreter createTemplateInterpreter(final TemplateInterpreter.Arguments args) {
125         return new TemplateInterpreter(args) {
126             @Override
127             protected Object getVariable(final Frame frame, final LexicalScope block, final ASTIdentifier identifier) {
128                 return Engine32.getVariable(this, frame, block, identifier);
129             }
130 
131             @Override
132             protected boolean isStrictOperand(final JexlNode node) {
133                 return false;
134             }
135 
136             @Override
137             protected boolean isTernaryProtected(final JexlNode node) {
138                 return Engine32.isTernaryProtected(this, node);
139             }
140         };
141     }
142 }