commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hen...@apache.org
Subject svn commit: r1210927 [1/7] - in /commons/proper/jexl/trunk: ./ src/main/java/org/apache/commons/jexl3/ src/main/java/org/apache/commons/jexl3/internal/ src/main/java/org/apache/commons/jexl3/internal/introspection/ src/main/java/org/apache/commons/jexl...
Date Tue, 06 Dec 2011 14:19:36 GMT
Author: henrib
Date: Tue Dec  6 14:19:33 2011
New Revision: 1210927

URL: http://svn.apache.org/viewvc?rev=1210927&view=rev
Log:
JEXL-123

Added:
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java   (with props)
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java   (with props)
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlExpression.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Expression.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlInfoHandle.java   (with props)
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlScript.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Script.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JxltEngine.java   (with props)
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Debugger.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java   (with props)
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Interpreter.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Script.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/UnifiedJEXL.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/AbstractExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/AbstractExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ArrayIterator.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ArrayIterator.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ArrayListWrapper.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ArrayListWrapper.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/BooleanGetExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/BooleanGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckGetExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/DuckGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/DuckSetExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/DuckSetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/EnumerationIterator.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/EnumerationIterator.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Introspector.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/IntrospectorBase.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListGetExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ListGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/ListSetExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ListSetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MapGetExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/MapGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MapSetExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/MapSetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/MethodExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/MethodExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/PropertyGetExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/PropertyGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/PropertySetExecutor.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/PropertySetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/Uberspect.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/JexlUberspect.java
      - copied, changed from r1209060, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/Uberspect.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/Util.java   (with props)
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/introspection/
Removed:
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Debugger.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Expression.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/ExpressionImpl.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Interpreter.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlThreadedArithmetic.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Script.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/UnifiedJEXL.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/AbstractExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ArrayIterator.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ArrayListWrapper.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/BooleanGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/DuckGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/DuckSetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/EnumerationIterator.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Introspector.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ListGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/ListSetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/MapGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/MapSetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/MethodExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/PropertyGetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/PropertySetExecutor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/IntrospectorBase.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/Uberspect.java
Modified:
    commons/proper/jexl/trunk/pom.xml
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlInfo.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/Main.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/MapContext.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/ObjectContext.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/ReadonlyContext.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/introspection/SandboxUberspect.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/introspection/Sandbox.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlNode.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngineFactory.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayLiteralTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/BitwiseOperatorTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/BlockTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/CacheTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ClassCreator.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ClassCreatorTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ForEachTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IfTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/Jexl.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JexlTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JexlTestCase.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/MapLiteralTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/MethodTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ParseFailuresTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PublicFieldsTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/SandboxTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/UnifiedJEXLTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/VarTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/WhileTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/examples/ArrayTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/examples/MethodPropertyTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/introspection/DiscoveryTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/internal/introspection/MethodKeyTest.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/junit/Asserter.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/junit/AsserterTest.java

Modified: commons/proper/jexl/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/pom.xml?rev=1210927&r1=1210926&r2=1210927&view=diff
==============================================================================
--- commons/proper/jexl/trunk/pom.xml (original)
+++ commons/proper/jexl/trunk/pom.xml Tue Dec  6 14:19:33 2011
@@ -25,7 +25,7 @@
     <groupId>org.apache.commons</groupId>
     <artifactId>commons-jexl3</artifactId>
     <version>3.0-SNAPSHOT</version>
-    <name>Commons JEXL</name>
+    <name>Commons JEXL3</name>
     <inceptionYear>2001</inceptionYear>
     <description>The Commons Jexl library is an implementation of the JSTL Expression Language with extensions.</description>
     <url>http://commons.apache.org/jexl/</url>
@@ -107,7 +107,7 @@
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
-            <version>3.8.2</version>
+            <version>4.10</version>
             <scope>test</scope>
         </dependency>
         <!-- For JSR-223 API -->
@@ -120,8 +120,8 @@
     </dependencies>
 
     <properties>
-        <maven.compile.source>1.5</maven.compile.source>
-        <maven.compile.target>1.5</maven.compile.target>
+        <maven.compile.source>1.6</maven.compile.source>
+        <maven.compile.target>1.6</maven.compile.target>
         <commons.componentid>jexl</commons.componentid>
         <commons.release.version>3.0</commons.release.version>
         <!-- The RC version used in the staging repository URL. -->
@@ -227,12 +227,13 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-checkstyle-plugin</artifactId>
-                <version>2.5</version>
+                <version>2.8</version>
                 <configuration>
                     <configLocation>${basedir}/src/main/config/checkstyle.xml</configLocation>
                     <excludes>org/apache/commons/jexl3/parser/*.java</excludes>
                     <headerLocation>${basedir}/src/main/config/header.txt</headerLocation>
                     <enableRulesSummary>false</enableRulesSummary>
+                    <inherited>false</inherited>
                 </configuration>
             </plugin>
             <plugin>
@@ -291,8 +292,6 @@
                     <excludes>
                       <exclude>org/apache/commons/jexl3/parser/**</exclude>
                       <exclude>org/apache/commons/jexl3/internal/**</exclude>
-                      <exclude>org/apache/commons/jexl2/parser/**</exclude>
-                      <exclude>org/apache/commons/jexl2/internal/**</exclude>
                     </excludes>
                 </configuration>
             </plugin>

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java?rev=1210927&r1=1210926&r2=1210927&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java Tue Dec  6 14:19:33 2011
@@ -63,31 +63,57 @@ public class JexlArithmetic {
 
     /**
      * Creates a JexlArithmetic.
-     * @param lenient whether this arithmetic is lenient or strict
+     * @param astrict whether this arithmetic is strict or lenient
      */
-    public JexlArithmetic(boolean lenient) {
-        this(lenient, MathContext.DECIMAL128, BIGD_SCALE);
+    public JexlArithmetic(boolean astrict) {
+        this(astrict, null, Integer.MIN_VALUE);
     }
 
     /**
      * Creates a JexlArithmetic.
-     * @param lenient whether this arithmetic is lenient or strict
+     * @param astrict whether this arithmetic is lenient or strict
      * @param bigdContext the math context instance to use for +,-,/,*,% operations on big decimals.
      * @param bigdScale the scale used for big decimals.
      */
-    public JexlArithmetic(boolean lenient, MathContext bigdContext, int bigdScale) {
-        this.strict = !lenient;
-        this.mathContext = bigdContext;
-        this.mathScale = bigdScale;
+    public JexlArithmetic(boolean astrict, MathContext bigdContext, int bigdScale) {
+        this.strict = astrict;
+        this.mathContext = bigdContext == null? MathContext.DECIMAL128 : bigdContext;
+        this.mathScale = bigdScale == Integer.MIN_VALUE? BIGD_SCALE : bigdScale;
     }
 
     /**
-     * Checks whether this JexlArithmetic instance triggers errors during evaluation
-     * when null is used as an operand.
-     * @return true if lenient, false if strict
+     * Apply options to this arithmetic which eventually may create another instance.
+     * @param options the {@link JexlEngine.Options} to use
+     * @return an arithmetic with those options set
+     */
+    public JexlArithmetic options(JexlEngine.Options options) {
+        boolean ostrict = options.isStrictArithmetic() == null
+                          ? this.strict
+                          : options.isStrictArithmetic().booleanValue();
+        MathContext bigdContext = options.getArithmeticMathContext();
+        if (bigdContext == null) {
+            bigdContext = mathContext;
+        }
+        int bigdScale = options.getArithmeticMathScale();
+        if (bigdScale == Integer.MIN_VALUE) {
+            bigdScale = mathScale;
+        }
+        if ((ostrict != this.strict)
+             || bigdScale != this.mathScale
+             || bigdContext != this.mathContext) {
+            return new JexlArithmetic(ostrict, bigdContext, bigdScale);
+        } else {
+            return this;
+        }
+    }
+
+    /**
+     * Checks whether this JexlArithmetic instance
+     * strictly considers null as an error when used as operand unexpectedly.
+     * @return true if strict, false if lenient
      */
-    public boolean isLenient() {
-        return !this.strict;
+    public boolean isStrict() {
+        return this.strict;
     }
 
     /**
@@ -126,7 +152,7 @@ public class JexlArithmetic {
      * @throws ArithmeticException if strict
      */
     protected Object controlNullNullOperands() {
-        if (!isLenient()) {
+        if (isStrict()) {
             throw new ArithmeticException(JexlException.NULL_OPERAND);
         }
         return Integer.valueOf(0);
@@ -137,7 +163,7 @@ public class JexlArithmetic {
      * @throws ArithmeticException if strict
      */
     protected void controlNullOperand() {
-        if (!isLenient()) {
+        if (isStrict()) {
             throw new ArithmeticException(JexlException.NULL_OPERAND);
         }
     }
@@ -193,7 +219,7 @@ public class JexlArithmetic {
                 || o instanceof Short
                 || o instanceof Character;
     }
-    
+
     /**
      * Whether we consider the narrow class as a potential candidate for narrowing the source.
      * @param narrow the target narrow class
@@ -210,7 +236,7 @@ public class JexlArithmetic {
      * @param narrow the attempted target class
      * @return  the narrowed number or the source if no narrowing was possible
      */
-    protected Number narrowNumber(Number original, Class<?> narrow) {
+    public Number narrowNumber(Number original, Class<?> narrow) {
         if (original == null) {
             return original;
         }
@@ -341,7 +367,7 @@ public class JexlArithmetic {
      * @param untyped an untyped array
      * @return the original array if the attempt to strictly type the array fails, a typed array otherwise
      */
-    protected Object narrowArrayType(Object[] untyped) {
+    public Object narrowArrayType(Object[] untyped) {
         final int size = untyped.length;
         Class<?> commonClass = null;
         if (size > 0) {
@@ -401,7 +427,7 @@ public class JexlArithmetic {
      * @return true if some arguments were narrowed and args array is modified,
      *         false if no narrowing occured and args array has not been modified
      */
-    protected boolean narrowArguments(Object[] args) {
+    public boolean narrowArguments(Object[] args) {
         boolean narrowed = false;
         for (int a = 0; a < args.length; ++a) {
             Object arg = args[a];
@@ -454,6 +480,9 @@ public class JexlArithmetic {
             return narrowBigInteger(left, right, result);
         } catch (java.lang.NumberFormatException nfe) {
             // Well, use strings!
+            if (left == null || right == null) {
+                controlNullOperand();
+            }
             return toString(left).concat(toString(right));
         }
     }
@@ -1099,5 +1128,4 @@ public class JexlArithmetic {
     public Number narrow(Number original) {
         return narrowNumber(original, null);
     }
-
 }
\ No newline at end of file

Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java?rev=1210927&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java Tue Dec  6 14:19:33 2011
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl3;
+
+import org.apache.commons.jexl3.internal.Engine;
+import java.util.Map;
+import org.apache.commons.jexl3.introspection.JexlUberspect;
+import org.apache.commons.logging.Log;
+
+/**
+ * Configure and builds a JexlEngine.
+ * <p>The <code>setSilent</code> and <code>setStrict</code> methods allow to fine-tune an engine instance behavior
+ * according to various error control needs. The strict flag tells the engine when and if null as operand is
+ * considered an error, the silent flag tells the engine what to do with the error
+ * (log as warning or throw exception).
+ * </p>
+ * <ul>
+ * <li>When "silent" &amp; "not-strict":
+ * <p> 0 & null should be indicators of "default" values so that even in an case of error,
+ * something meaningfull can still be inferred; may be convenient for configurations.
+ * </p>
+ * </li>
+ * <li>When "silent" &amp; "strict":
+ * <p>One should probably consider using null as an error case - ie, every object
+ * manipulated by JEXL should be valued; the ternary operator, especially the '?:' form
+ * can be used to workaround exceptional cases.
+ * Use case could be configuration with no implicit values or defaults.
+ * </p>
+ * </li>
+ * <li>When "not-silent" &amp; "not-stict":
+ * <p>The error control grain is roughly on par with JEXL 1.0</p>
+ * </li>
+ * <li>When "not-silent" &amp; "strict":
+ * <p>The finest error control grain is obtained; it is the closest to Java code -
+ * still augmented by "script" capabilities regarding automated conversions & type matching.
+ * </p>
+ * </li>
+ * </ul>
+ */
+public class JexlBuilder {
+    /**
+     * The JexlUberspect instance.
+     */
+    protected JexlUberspect uberspect = null;
+    /**
+     * The Log to which all JexlEngine messages will be logged.
+     */
+    protected Log logger = null;
+    /**
+     * Whether expressions evaluated by this engine will throw exceptions (false) or
+     * return null (true) on errors. Default is false.
+     */
+    protected Boolean silent = null;
+    /**
+     * Whether this engine is in lenient or strict mode; if unspecified, use the arithmetic lenient property.
+     */
+    protected Boolean strict = null;
+    /**
+     * Whether error messages will carry debugging information.
+     */
+    protected Boolean debug = null;
+    /**
+     *  The map of 'prefix:function' to object implementing the namespaces.
+     */
+    protected Map<String, Object> namespaces = null;
+    /**
+     * The {@link JexlArithmetic} instance.
+     */
+    protected JexlArithmetic arithmetic = null;
+    /**
+     * The cache size.
+     */
+    protected int cache = -1;
+
+    /**
+     * Sets the JexlUberspect instance the engine will use.
+     * @param u the uberspect
+     * @return this builder
+     */
+    public JexlBuilder uberspect(JexlUberspect u) {
+        this.uberspect = u;
+        return this;
+    }
+
+    /** @return the uberspect */
+    public JexlUberspect uberspect() {
+        return this.uberspect;
+    }
+
+    /**
+     * Sets the JexlArithmetic instance the engine will use.
+     * @param a the arithmetic
+     * @return this builder
+     */
+    public JexlBuilder arithmetic(JexlArithmetic a) {
+        this.arithmetic = a;
+        return this;
+    }
+
+    /** @return the arithmetic */
+    public JexlArithmetic arithmetic() {
+        return this.arithmetic;
+    }
+
+    /**
+     * Sets the o.a.c.Log instance to use.
+     * @param l the logger
+     * @return this builder
+     */
+    public JexlBuilder logger(Log l) {
+        this.logger = l;
+        return this;
+    }
+
+    /** @return the logger */
+    public Log logger() {
+        return this.logger;
+    }
+
+    /**
+     * Sets whether the engine will throw JexlException during evaluation when an error is triggered.
+     * @param flag true means no JexlException will occur, false allows them
+     * @return this builder
+     */
+    public JexlBuilder silent(boolean flag) {
+        this.silent = flag;
+        return this;
+    }
+
+    /** @return the silent error handling flag */
+    public Boolean silent() {
+        return this.silent;
+    }
+
+    /**
+     * Sets whether the engine considers unknown variables, methods, functions and constructors as errors or
+     * evaluates them as null.
+     * @param flag true means strict error reporting, false allows them to be evaluated as null
+     * @return this builder
+     */
+    public JexlBuilder strict(boolean flag) {
+        this.strict = flag;
+        return this;
+    }
+
+    /** @return true if strict, false otherwise */
+    public Boolean strict() {
+        return this.strict;
+    }
+
+    /**
+     * Sets whether the engine will report debugging information when error occurs.
+     * @param flag true implies debug is on, false implies debug is off.
+     * @return this builder
+     */
+    public JexlBuilder debug(boolean flag) {
+        this.debug = flag;
+        return this;
+    }
+
+    /** @return the debugging information flag */
+    public Boolean debug() {
+        return this.debug;
+    }
+
+    /**
+     * Sets the map of function namespaces the engine will use.
+     * <p>
+     * Each entry key is used as a prefix, each entry value used as a bean implementing
+     * methods; an expression like 'nsx:method(123)' will thus be solved by looking at
+     * a registered bean named 'nsx' that implements method 'method' in that map.
+     * If all methods are static, you may use the bean class instead of an instance as value.
+     * </p>
+     * <p>
+     * If the entry value is a class that has one contructor taking a JexlContext as argument, an instance
+     * of the namespace will be created at evaluation time. It might be a good idea to derive a JexlContext
+     * to carry the information used by the namespace to avoid variable space pollution and strongly type
+     * the constructor with this specialized JexlContext.
+     * </p>
+     * <p>
+     * The key or prefix allows to retrieve the bean that plays the role of the namespace.
+     * If the prefix is null, the namespace is the top-level namespace allowing to define
+     * top-level user defined namespaces ( ie: myfunc(...) )
+     * </p>
+     * <p>Note that the JexlContext is also used to try to solve top-level namespaces. This allows ObjectContext
+     * derived instances to call methods on the wrapped object.</p>
+     * @param ns the map of namespaces
+     * @return this builder
+     */
+    public JexlBuilder namespaces(Map<String, Object> ns) {
+        this.namespaces = ns;
+        return this;
+    }
+
+    /**
+     * @return the map of namespaces.
+     */
+    public Map<String, Object> namespaces() {
+        return this.namespaces;
+    }
+
+    /**
+     * Sets the expression cache size the engine will use.
+     * <p>The cache will contain at most <code>size</code> expressions. Note that
+     * all JEXL caches are held through SoftReferences and may be garbage-collected.</p>
+     * @param size if not strictly positive, no cache is used.
+     * @return this builder
+     */
+    public JexlBuilder cache(int size) {
+        this.cache = size;
+        return this;
+    }
+
+    /**@return the cache size */
+    public int cache() {
+        return cache;
+    }
+
+    /**
+     * @return a {@link JexlEngine} instance
+     */
+    public JexlEngine create() {
+        return new Engine(this);
+    }
+}

Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java?rev=1210927&r1=1210926&r2=1210927&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEngine.java Tue Dec  6 14:19:33 2011
@@ -18,41 +18,17 @@ package org.apache.commons.jexl3;
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.StringReader;
 import java.io.Reader;
 import java.net.URL;
-import java.net.URLConnection;
-import java.lang.ref.SoftReference;
-import java.util.ArrayList;
 import java.util.Map;
-import java.util.Set;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map.Entry;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.apache.commons.jexl3.parser.ParseException;
-import org.apache.commons.jexl3.parser.Parser;
-import org.apache.commons.jexl3.parser.JexlNode;
-import org.apache.commons.jexl3.parser.TokenMgrError;
-import org.apache.commons.jexl3.parser.ASTJexlScript;
-
-import org.apache.commons.jexl3.introspection.Uberspect;
-import org.apache.commons.jexl3.introspection.JexlMethod;
-import org.apache.commons.jexl3.parser.ASTArrayAccess;
-import org.apache.commons.jexl3.parser.ASTIdentifier;
-import org.apache.commons.jexl3.parser.ASTReference;
+import java.math.MathContext;
+import org.apache.commons.jexl3.introspection.JexlUberspect;
 
 /**
  * <p>
- * Creates and evaluates Expression and Script objects.
- * Determines the behavior of Expressions & Scripts during their evaluation with respect to:
+ * Creates and evaluates JexlExpression and JexlScript objects.
+ * Determines the behavior of expressions & scripts during their evaluation with respect to:
  * <ul>
  *  <li>Introspection, see {@link Uberspect}</li>
  *  <li>Arithmetic & comparison, see {@link JexlArithmetic}</li>
@@ -60,33 +36,6 @@ import org.apache.commons.jexl3.parser.A
  *  <li>Logging</li>
  * </ul>
  * </p>
- * <p>The <code>setSilent</code> and <code>setLenient</code> methods allow to fine-tune an engine instance behavior
- * according to various error control needs. The lenient/strict flag tells the engine when and if null as operand is
- * considered an error, the silent/verbose flag tells the engine what to do with the error
- * (log as warning or throw exception).
- * </p>
- * <ul>
- * <li>When "silent" &amp; "lenient":
- * <p> 0 & null should be indicators of "default" values so that even in an case of error,
- * something meaningfull can still be inferred; may be convenient for configurations.
- * </p>
- * </li>
- * <li>When "silent" &amp; "strict":
- * <p>One should probably consider using null as an error case - ie, every object
- * manipulated by JEXL should be valued; the ternary operator, especially the '?:' form
- * can be used to workaround exceptional cases.
- * Use case could be configuration with no implicit values or defaults.
- * </p>
- * </li>
- * <li>When "verbose" &amp; "lenient":
- * <p>The error control grain is roughly on par with JEXL 1.0</p>
- * </li>
- * <li>When "verbose" &amp; "strict":
- * <p>The finest error control grain is obtained; it is the closest to Java code -
- * still augmented by "script" capabilities regarding automated conversions & type matching.
- * </p>
- * </li>
- * </ul>
  * <p>
  * Note that methods that evaluate expressions may throw <em>unchecked</em> exceptions;
  * The {@link JexlException} are thrown in "non-silent" mode but since these are
@@ -94,346 +43,128 @@ import org.apache.commons.jexl3.parser.A
  * </p>
  * @since 2.0
  */
-public class JexlEngine {
+public abstract class JexlEngine {
     /**
-     * An empty/static/non-mutable JexlContext used instead of null context.
+     * Script evaluation options.
      */
-    public static final JexlContext EMPTY_CONTEXT = new JexlContext() {
-        /** {@inheritDoc} */
-        public Object get(String name) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        public boolean has(String name) {
-            return false;
-        }
-
-        /** {@inheritDoc} */
-        public void set(String name, Object value) {
-            throw new UnsupportedOperationException("Not supported in void context.");
-        }
-    };
-
-    /**
-     *  Gets the default instance of Uberspect.
-     * <p>This is lazily initialized to avoid building a default instance if there
-     * is no use for it. The main reason for not using the default Uberspect instance is to
-     * be able to use a (low level) introspector created with a given logger
-     * instead of the default one.</p>
-     * <p>Implemented as on demand holder idiom.</p>
-     */
-    private static final class UberspectHolder {
-        /** The default uberspector that handles all introspection patterns. */
-        private static final Uberspect UBERSPECT =
-                new org.apache.commons.jexl3.internal.introspection.Uberspect(LogFactory.getLog(JexlEngine.class));
-
-        /** Non-instantiable. */
-        private UberspectHolder() {
-        }
-    }
-    /**
-     * The Uberspect instance.
-     */
-    protected final Uberspect uberspect;
-    /**
-     * The JexlArithmetic instance.
-     */
-    protected final JexlArithmetic arithmetic;
-    /**
-     * The Log to which all JexlEngine messages will be logged.
-     */
-    protected final Log logger;
-    /**
-     * The singleton ExpressionFactory also holds a single instance of
-     * {@link Parser}.
-     * When parsing expressions, ExpressionFactory synchronizes on Parser.
-     */
-    protected final Parser parser = new Parser(new StringReader(";")); //$NON-NLS-1$
-    /**
-     * Whether expressions evaluated by this engine will throw exceptions (false) or 
-     * return null (true) on errors. Default is false.
-     */
-    protected boolean silent = false;
-    /**
-     * Whether this engine is in lenient or strict mode; if unspecified, use the arithmetic lenient property.
-     */
-    protected Boolean strict = null;
-    /**
-     * Whether error messages will carry debugging information.
-     */
-    protected boolean debug = true;
-    /**
-     *  The map of 'prefix:function' to object implementing the functions.
-     */
-    protected Map<String, Object> functions = Collections.emptyMap();
-    /**
-     * The expression cache.
-     */
-    protected SoftCache<String, ASTJexlScript> cache = null;
-    /**
-     * The default cache load factor.
-     */
-    private static final float LOAD_FACTOR = 0.75f;
+    public interface Options {
+        /**
+         * Sets whether the engine will throw a {@link JexlException} when an error is encountered during evaluation.
+         * @return true if silent, false otherwise
+         */
+        Boolean isSilent();
 
-    /**
-     * Creates an engine with default arguments.
-     */
-    public JexlEngine() {
-        this(null, null, null, null);
-    }
+        /**
+         * Checks whether the engine considers unknown variables, methods, functions and constructors as errors or
+         * evaluates them as null.
+         * @return true if strict, false otherwise
+         */
+        Boolean isStrict();
+        
+        /**
+         * The namespaces to use for evaluation.
+         * @return the map of namespaces
+         */
+        Map<String, Object> getNamespaces();
+        
+        /**
+         * Checks whether the arithmetic triggers errors during evaluation when null is used as an operand.
+         * @return true if strict, false otherwise
+         */
+        Boolean isStrictArithmetic();
 
-    /**
-     * Creates a JEXL engine using the provided {@link Uberspect}, (@link JexlArithmetic),
-     * a function map and logger.
-     * @param anUberspect to allow different introspection behaviour
-     * @param anArithmetic to allow different arithmetic behaviour
-     * @param theFunctions an optional map of functions (@link setFunctions)
-     * @param log the logger for various messages
-     */
-    public JexlEngine(Uberspect anUberspect, JexlArithmetic anArithmetic, Map<String, Object> theFunctions, Log log) {
-        this.uberspect = anUberspect == null ? getUberspect(log) : anUberspect;
-        if (log == null) {
-            log = LogFactory.getLog(JexlEngine.class);
-        }
-        this.logger = log;
-        this.arithmetic = anArithmetic == null ? new JexlArithmetic(true) : anArithmetic;
-        if (theFunctions != null) {
-            this.functions = theFunctions;
-        }
-    }
+        /**
+         * The MathContext instance used for +,-,/,*,% operations on big decimals.
+         * @return the math context
+         */
+        MathContext getArithmeticMathContext();
 
-    /**
-     *  Gets the default instance of Uberspect.
-     * <p>This is lazily initialized to avoid building a default instance if there
-     * is no use for it. The main reason for not using the default Uberspect instance is to
-     * be able to use a (low level) introspector created with a given logger
-     * instead of the default one.</p>
-     * @param logger the logger to use for the underlying Uberspect
-     * @return Uberspect the default uberspector instance.
-     */
-    public static Uberspect getUberspect(Log logger) {
-        if (logger == null || logger.equals(LogFactory.getLog(JexlEngine.class))) {
-            return UberspectHolder.UBERSPECT;
-        }
-        return new org.apache.commons.jexl3.internal.introspection.Uberspect(logger);
+        /**
+         * The BigDecimal scale used for comparison and coercion operations.
+         * @return the scale
+         */
+        int getArithmeticMathScale();
     }
-
+    
     /**
      * Gets this engine underlying uberspect.
      * @return the uberspect
      */
-    public Uberspect getUberspect() {
-        return uberspect;
-    }
-
+    public abstract JexlUberspect getUberspect();
+    
     /**
      * Gets this engine underlying arithmetic.
      * @return the arithmetic
      */
-    public JexlArithmetic getArithmetic() {
-        return arithmetic;
-    }
-
+    public abstract JexlArithmetic getArithmetic();
+    
     /**
-     * Sets whether this engine reports debugging information when error occurs.
-     * <p>This method is <em>not</em> thread safe; it should be called as an optional step of the JexlEngine
-     * initialization code before expression creation &amp; evaluation.</p>
-     * @see JexlEngine#setSilent
-     * @see JexlEngine#setLenient
-     * @param flag true implies debug is on, false implies debug is off.
+     * Gets a Jexl Template engine instance.
+     * @return a Jexl Template engine
      */
-    public void setDebug(boolean flag) {
-        this.debug = flag;
-    }
+    public abstract JxltEngine jxlt();
 
     /**
-     * Checks whether this engine is in debug mode.
-     * @return true if debug is on, false otherwise
+     * Retrieves the map of function namespaces.
+     * @return the map passed in setFunctions or the empty map if the
+     * original was null.
      */
-    public boolean isDebug() {
-        return this.debug;
-    }
-
+    public abstract Map<String, Object> getFunctions();
     /**
-     * Sets whether this engine throws JexlException during evaluation when an error is triggered.
-     * <p>This method is <em>not</em> thread safe; it should be called as an optional step of the JexlEngine
-     * initialization code before expression creation &amp; evaluation.</p>
-     * @see JexlEngine#setDebug
-     * @see JexlEngine#setLenient
-     * @param flag true means no JexlException will occur, false allows them
+     * Checks whether this engine is in debug mode.
+     * @return true if debug is on, false otherwise
      */
-    public void setSilent(boolean flag) {
-        this.silent = flag;
-    }
+    public abstract boolean isDebug();
 
     /**
      * Checks whether this engine throws JexlException during evaluation.
      * @return true if silent, false (default) otherwise
      */
-    public boolean isSilent() {
-        return this.silent;
-    }
-
-    /**
-     * Sets whether this engine considers unknown variables, methods and constructors as errors or evaluates them
-     * as null.
-     * <p>This method is <em>not</em> thread safe; it should be called as an optional step of the JexlEngine
-     * initialization code before expression creation &amp; evaluation.</p>
-     * <p>As of 3.0, you need a JexlThreadedArithmetic instance for this call to also modify the JexlArithmetic
-     * leniency behavior.</p>
-     * @see JexlEngine#setSilent
-     * @see JexlEngine#setDebug
-     * @param flag true means no JexlException will occur, false allows them
-     */
-    public void setLenient(boolean flag) {
-        if (arithmetic instanceof JexlThreadedArithmetic) {
-            JexlThreadedArithmetic.setLenient(Boolean.valueOf(flag));
-        } else {
-            strict = flag ? Boolean.FALSE : Boolean.TRUE;
-        }
-    }
-
-    /**
-     * Checks whether this engine considers unknown variables, methods and constructors as errors.
-     * <p>If not explicitly set, the arithmetic leniency value applies.</p>
-     * @return true if lenient, false if strict
-     */
-    public boolean isLenient() {
-        return strict == null ? arithmetic.isLenient() : !strict.booleanValue();
-    }
-
-    /**
-     * Sets whether this engine behaves in strict or lenient mode.
-     * Equivalent to setLenient(!flag).
-     * @param flag true for strict, false for lenient
-     */
-    public final void setStrict(boolean flag) {
-        setLenient(!flag);
-    }
+    public abstract boolean isSilent();
 
     /**
-     * Checks whether this engine behaves in strict or lenient mode.
-     * Equivalent to !isLenient().
-     * @return true for strict, false for lenient
+     * Checks whether the engine considers unknown variables, methods, functions and constructors as errors.
+     * @return true if strict, false otherwise
      */
-    public final boolean isStrict() {
-        return !isLenient();
-    }
-
+    public abstract boolean isStrict();
+    
     /**
      * Sets the class loader used to discover classes in 'new' expressions.
-     * <p>This method should be called as an optional step of the JexlEngine
+     * <p>This method is <em>not</em> thread safe; it should be called as an optional step of the JexlEngine
      * initialization code before expression creation &amp; evaluation.</p>
      * @param loader the class loader to use
      */
-    public void setClassLoader(ClassLoader loader) {
-        uberspect.setClassLoader(loader);
-    }
-
+    public abstract void setClassLoader(ClassLoader loader);
+    
     /**
-     * Sets a cache for expressions of the defined size.
-     * <p>The cache will contain at most <code>size</code> expressions. Note that
-     * all JEXL caches are held through SoftReferences and may be garbage-collected.</p>
-     * @param size if not strictly positive, no cache is used.
-     */
-    public void setCache(int size) {
-        // since the cache is only used during parse, use same sync object
-        synchronized (parser) {
-            if (size <= 0) {
-                cache = null;
-            } else if (cache == null || cache.size() != size) {
-                cache = new SoftCache<String, ASTJexlScript>(size);
-            }
-        }
-    }
-
-    /**
-     * Sets the map of function namespaces.
-     * <p>
-     * This method is <em>not</em> thread safe; it should be called as an optional step of the JexlEngine
-     * initialization code before expression creation &amp; evaluation.
-     * </p>
-     * <p>
-     * Each entry key is used as a prefix, each entry value used as a bean implementing
-     * methods; an expression like 'nsx:method(123)' will thus be solved by looking at
-     * a registered bean named 'nsx' that implements method 'method' in that map.
-     * If all methods are static, you may use the bean class instead of an instance as value.
-     * </p>
-     * <p>
-     * If the entry value is a class that has one contructor taking a JexlContext as argument, an instance
-     * of the namespace will be created at evaluation time. It might be a good idea to derive a JexlContext
-     * to carry the information used by the namespace to avoid variable space pollution and strongly type
-     * the constructor with this specialized JexlContext.
-     * </p>
-     * <p>
-     * The key or prefix allows to retrieve the bean that plays the role of the namespace.
-     * If the prefix is null, the namespace is the top-level namespace allowing to define
-     * top-level user defined functions ( ie: myfunc(...) )
-     * </p>
-     * <p>Note that the JexlContext is also used to try to solve top-level functions. This allows ObjectContext
-     * derived instances to call methods on the wrapped object.</p>
-     * @param funcs the map of functions that should not mutate after the call; if null
-     * is passed, the empty collection is used.
-     */
-    public void setFunctions(Map<String, Object> funcs) {
-        functions = funcs != null ? funcs : Collections.<String, Object>emptyMap();
-    }
-
-    /**
-     * Retrieves the map of function namespaces.
-     *
-     * @return the map passed in setFunctions or the empty map if the
-     * original was null.
-     */
-    public Map<String, Object> getFunctions() {
-        return functions;
-    }
-
-    /**
-     * An overridable through covariant return Expression creator.
-     * @param text the script text
-     * @param tree the parse AST tree
-     * @return the script instance
+     * Clears the expression cache.
      */
-    protected Expression createExpression(ASTJexlScript tree, String text) {
-        return new JexlScript(this, text, tree);
-    }
+    public abstract void clearCache();
 
     /**
-     * Creates an Expression from a String containing valid
+     * Creates an JexlExpression from a String containing valid
      * JEXL syntax.  This method parses the expression which
      * must contain either a reference or an expression.
      * @param expression A String containing valid JEXL syntax
-     * @return An Expression object which can be evaluated with a JexlContext
+     * @return An JexlExpression object which can be evaluated with a JexlContext
      * @throws JexlException An exception can be thrown if there is a problem
-     *      parsing this expression, or if the expression is neither an
-     *      expression nor a reference.
+     * parsing this expression, or if the expression is neither an
+     * expression nor a reference.
      */
-    public Expression createExpression(String expression) {
-        return createExpression(expression, null);
-    }
+    public abstract JexlExpression createExpression(String expression);
 
     /**
-     * Creates an Expression from a String containing valid
+     * Creates an JexlExpression from a String containing valid
      * JEXL syntax.  This method parses the expression which
      * must contain either a reference or an expression.
      * @param expression A String containing valid JEXL syntax
-     * @return An Expression object which can be evaluated with a JexlContext
+     * @return An JexlExpression object which can be evaluated with a JexlContext
      * @param info An info structure to carry debugging information if needed
      * @throws JexlException An exception can be thrown if there is a problem
-     *      parsing this expression, or if the expression is neither an
-     *      expression or a reference.
+     * parsing this expression, or if the expression is neither an
+     * expression or a reference.
      */
-    public Expression createExpression(String expression, JexlInfo info) {
-        // Parse the expression
-        ASTJexlScript tree = parse(expression, info, null);
-        if (tree.jjtGetNumChildren() > 1) {
-            logger.warn("The JEXL Expression created will be a reference"
-                    + " to the first expression from the supplied script: \"" + expression + "\" ");
-        }
-        return createExpression(tree, expression);
-    }
+    public abstract JexlExpression createExpression(String expression, JexlInfo info);
 
     /**
      * Creates a Script from a String containing valid JEXL syntax.
@@ -443,9 +174,7 @@ public class JexlEngine {
      * @return A {@link Script} which can be executed using a {@link JexlContext}.
      * @throws JexlException if there is a problem parsing the script.
      */
-    public JexlScript createScript(String scriptText) {
-        return createScript(scriptText, null, null);
-    }
+    public abstract JexlScript createScript(String scriptText);
 
     /**
      * Creates a Script from a String containing valid JEXL syntax.
@@ -456,9 +185,7 @@ public class JexlEngine {
      * @return A {@link Script} which can be executed using a {@link JexlContext}.
      * @throws JexlException if there is a problem parsing the script.
      */
-    public JexlScript createScript(String scriptText, String... names) {
-        return createScript(scriptText, null, names);
-    }
+    public abstract JexlScript createScript(String scriptText, String... names);
 
     /**
      * Creates a Script from a String containing valid JEXL syntax.
@@ -472,76 +199,34 @@ public class JexlEngine {
      * @return A {@link Script} which can be executed using a {@link JexlContext}.
      * @throws JexlException if there is a problem parsing the script.
      */
-    public JexlScript createScript(String scriptText, JexlInfo info, String[] names) {
-        if (scriptText == null) {
-            throw new NullPointerException("scriptText is null");
-        }
-        // Parse the expression
-        ASTJexlScript tree = parse(scriptText, info, new Scope(names));
-        return createScript(tree, scriptText);
-    }
-
-    /**
-     * An overridable through covariant return Script creator.
-     * @param text the script text
-     * @param tree the parse AST tree
-     * @return the script instance
-     */
-    protected JexlScript createScript(ASTJexlScript tree, String text) {
-        return new JexlScript(this, text, tree);
-    }
+    public abstract JexlScript createScript(String scriptText, JexlInfo info, String[] names);
 
     /**
      * Creates a Script from a {@link File} containing valid JEXL syntax.
      * This method parses the script and validates the syntax.
      *
      * @param scriptFile A {@link File} containing valid JEXL syntax.
-     *      Must not be null. Must be a readable file.
+     * Must not be null. Must be a readable file.
      * @return A {@link Script} which can be executed with a
-     *      {@link JexlContext}.
+     * {@link JexlContext}.
      * @throws IOException if there is a problem reading the script.
      * @throws JexlException if there is a problem parsing the script.
      */
-    public Script createScript(File scriptFile) throws IOException {
-        if (scriptFile == null) {
-            throw new NullPointerException("scriptFile is null");
-        }
-        if (!scriptFile.canRead()) {
-            throw new IOException("Can't read scriptFile (" + scriptFile.getCanonicalPath() + ")");
-        }
-        BufferedReader reader = new BufferedReader(new FileReader(scriptFile));
-        JexlInfo info = null;
-        if (debug) {
-            info = createInfo(scriptFile.getName(), 0, 0);
-        }
-        return createScript(readerToString(reader), info, null);
-    }
+    public abstract JexlScript createScript(File scriptFile) throws IOException;
 
     /**
      * Creates a Script from a {@link URL} containing valid JEXL syntax.
      * This method parses the script and validates the syntax.
      *
      * @param scriptUrl A {@link URL} containing valid JEXL syntax.
-     *      Must not be null. Must be a readable file.
+     * Must not be null. Must be a readable file.
      * @return A {@link Script} which can be executed with a
-     *      {@link JexlContext}.
+     * {@link JexlContext}.
      * @throws IOException if there is a problem reading the script.
      * @throws JexlException if there is a problem parsing the script.
      */
-    public Script createScript(URL scriptUrl) throws IOException {
-        if (scriptUrl == null) {
-            throw new NullPointerException("scriptUrl is null");
-        }
-        URLConnection connection = scriptUrl.openConnection();
+    public abstract JexlScript createScript(URL scriptUrl) throws IOException;
 
-        BufferedReader reader = new BufferedReader(
-                new InputStreamReader(connection.getInputStream()));
-        JexlInfo info = null;
-        if (debug) {
-            info = createInfo(scriptUrl.toString(), 0, 0);
-        }
-        return createScript(readerToString(reader), info, null);
-    }
 
     /**
      * Accesses properties of a bean using an expression.
@@ -557,9 +242,7 @@ public class JexlEngine {
      * @return the value of the property
      * @throws JexlException if there is an error parsing the expression or during evaluation
      */
-    public Object getProperty(Object bean, String expr) {
-        return getProperty(null, bean, expr);
-    }
+    public abstract Object getProperty(Object bean, String expr);
 
     /**
      * Accesses properties of a bean using an expression.
@@ -572,31 +255,7 @@ public class JexlEngine {
      * @return the value of the property
      * @throws JexlException if there is an error parsing the expression or during evaluation
      */
-    public Object getProperty(JexlContext context, Object bean, String expr) {
-        if (context == null) {
-            context = EMPTY_CONTEXT;
-        }
-        // synthetize expr using register
-        expr = "#0" + (expr.charAt(0) == '[' ? "" : ".") + expr + ";";
-        try {
-            parser.ALLOW_REGISTERS = true;
-            Scope frame = new Scope("#0");
-            ASTJexlScript script = parse(expr, null, frame);
-            JexlNode node = script.jjtGetChild(0);
-            Interpreter interpreter = createInterpreter(context);
-            // set frame
-            interpreter.setFrame(script.createFrame(bean));
-            return node.jjtAccept(interpreter, null);
-        } catch (JexlException xjexl) {
-            if (silent) {
-                logger.warn(xjexl.getMessage(), xjexl.getCause());
-                return null;
-            }
-            throw xjexl;
-        } finally {
-            parser.ALLOW_REGISTERS = false;
-        }
-    }
+    public abstract Object getProperty(JexlContext context, Object bean, String expr);
 
     /**
      * Assign properties of a bean using an expression.
@@ -612,9 +271,7 @@ public class JexlEngine {
      * @param value the value of the property
      * @throws JexlException if there is an error parsing the expression or during evaluation
      */
-    public void setProperty(Object bean, String expr, Object value) {
-        setProperty(null, bean, expr, value);
-    }
+    public abstract void setProperty(Object bean, String expr, Object value);
 
     /**
      * Assign properties of a bean using an expression.
@@ -627,32 +284,7 @@ public class JexlEngine {
      * @param value the value of the property
      * @throws JexlException if there is an error parsing the expression or during evaluation
      */
-    public void setProperty(JexlContext context, Object bean, String expr, Object value) {
-        if (context == null) {
-            context = EMPTY_CONTEXT;
-        }
-        // synthetize expr using registers
-        expr = "#0" + (expr.charAt(0) == '[' ? "" : ".") + expr + "=" + "#1" + ";";
-        try {
-            parser.ALLOW_REGISTERS = true;
-            Scope frame = new Scope("#0", "#1");
-            ASTJexlScript script = parse(expr, null, frame);
-            JexlNode node = script.jjtGetChild(0);
-            Interpreter interpreter = createInterpreter(context);
-            // set the registers
-            interpreter.setFrame(script.createFrame(bean, value));
-            node.jjtAccept(interpreter, null);
-        } catch (JexlException xjexl) {
-            if (silent) {
-                logger.warn(xjexl.getMessage(), xjexl.getCause());
-                return;
-            }
-            throw xjexl;
-        } finally {
-            parser.ALLOW_REGISTERS = false;
-        }
-    }
-
+    public abstract void setProperty(JexlContext context, Object bean, String expr, Object value);
     /**
      * Invokes an object's method by name and arguments.
      * @param obj the method's invoker object
@@ -661,38 +293,7 @@ public class JexlEngine {
      * @return the method returned value or null if it failed and engine is silent
      * @throws JexlException if method could not be found or failed and engine is not silent
      */
-    public Object invokeMethod(Object obj, String meth, Object... args) {
-        JexlException xjexl = null;
-        Object result = null;
-        final JexlInfo info = jexlInfo();
-        JexlInfo.Handle handle = new JexlInfo.Handle() {
-            public JexlInfo jexlInfo() {
-                return info;
-            }
-        };
-        try {
-            JexlMethod method = uberspect.getMethod(obj, meth, args, handle);
-            if (method == null && arithmetic.narrowArguments(args)) {
-                method = uberspect.getMethod(obj, meth, args, handle);
-            }
-            if (method != null) {
-                result = method.invoke(obj, args);
-            } else {
-                xjexl = new JexlException(info, "failed finding method " + meth);
-            }
-        } catch (Exception xany) {
-            xjexl = new JexlException(info, "failed executing method " + meth, xany);
-        } finally {
-            if (xjexl != null) {
-                if (silent) {
-                    logger.warn(xjexl.getMessage(), xjexl.getCause());
-                    return null;
-                }
-                throw xjexl;
-            }
-        }
-        return result;
-    }
+    public abstract Object invokeMethod(Object obj, String meth, Object... args);
 
     /**
      * Creates a new instance of an object using the most appropriate constructor
@@ -702,9 +303,7 @@ public class JexlEngine {
      * @param args the constructor arguments
      * @return the created object instance or null on failure when silent
      */
-    public <T> T newInstance(Class<? extends T> clazz, Object... args) {
-        return clazz.cast(doCreateInstance(clazz, args));
-    }
+    public abstract <T> T newInstance(Class<? extends T> clazz, Object... args);
 
     /**
      * Creates a new instance of an object using the most appropriate constructor
@@ -713,559 +312,8 @@ public class JexlEngine {
      * @param args the constructor arguments
      * @return the created object instance or null on failure when silent
      */
-    public Object newInstance(String clazz, Object... args) {
-        return doCreateInstance(clazz, args);
-    }
-
-    /**
-     * Creates a new instance of an object using the most appropriate constructor
-     * based on the arguments.
-     * @param clazz the class to instantiate
-     * @param args the constructor arguments
-     * @return the created object instance or null on failure when silent
-     */
-    protected Object doCreateInstance(Object clazz, Object... args) {
-        JexlException xjexl = null;
-        Object result = null;
-        final JexlInfo info = jexlInfo();
-        JexlInfo.Handle handle = new JexlInfo.Handle() {
-            public JexlInfo jexlInfo() {
-                return info;
-            }
-        };
-        try {
-            JexlMethod ctor = uberspect.getConstructor(clazz, args, handle);
-            if (ctor == null && arithmetic.narrowArguments(args)) {
-                ctor = uberspect.getConstructor(clazz, args, handle);
-            }
-            if (ctor != null) {
-                result = ctor.invoke(clazz, args);
-            } else {
-                xjexl = new JexlException(info, "failed finding constructor for " + clazz.toString());
-            }
-        } catch (Exception xany) {
-            xjexl = new JexlException(info, "failed executing constructor for " + clazz.toString(), xany);
-        } finally {
-            if (xjexl != null) {
-                if (silent) {
-                    logger.warn(xjexl.getMessage(), xjexl.getCause());
-                    return null;
-                }
-                throw xjexl;
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Creates an interpreter.
-     * @param context a JexlContext; if null, the EMPTY_CONTEXT is used instead.
-     * @return an Interpreter
-     */
-    protected Interpreter createInterpreter(JexlContext context) {
-        return createInterpreter(context, isStrict(), isSilent());
-    }
-
-    /**
-     * Creates an interpreter.
-     * @param context a JexlContext; if null, the EMPTY_CONTEXT is used instead.
-     * @param strictFlag whether the interpreter runs in strict mode
-     * @param silentFlag whether the interpreter runs in silent mode
-     * @return an Interpreter
-     */
-    protected Interpreter createInterpreter(JexlContext context, boolean strictFlag, boolean silentFlag) {
-        return new Interpreter(this, context == null ? EMPTY_CONTEXT : context, strictFlag, silentFlag);
-    }
-
-    /**
-     * A soft reference on cache.
-     * <p>The cache is held through a soft reference, allowing it to be GCed under
-     * memory pressure.</p>
-     * @param <K> the cache key entry type
-     * @param <V> the cache key value type
-     */
-    protected class SoftCache<K, V> {
-        /**
-         * The cache size.
-         */
-        private final int size;
-        /**
-         * The soft reference to the cache map.
-         */
-        private SoftReference<Map<K, V>> ref = null;
-
-        /**
-         * Creates a new instance of a soft cache.
-         * @param theSize the cache size
-         */
-        SoftCache(int theSize) {
-            size = theSize;
-        }
-
-        /**
-         * Returns the cache size.
-         * @return the cache size
-         */
-        int size() {
-            return size;
-        }
-
-        /**
-         * Clears the cache.
-         */
-        void clear() {
-            ref = null;
-        }
-
-        /**
-         * Produces the cache entry set.
-         * @return the cache entry set
-         */
-        Set<Entry<K, V>> entrySet() {
-            Map<K, V> map = ref != null ? ref.get() : null;
-            return map != null ? map.entrySet() : Collections.<Entry<K, V>>emptySet();
-        }
-
-        /**
-         * Gets a value from cache.
-         * @param key the cache entry key
-         * @return the cache entry value
-         */
-        V get(K key) {
-            final Map<K, V> map = ref != null ? ref.get() : null;
-            return map != null ? map.get(key) : null;
-        }
-
-        /**
-         * Puts a value in cache.
-         * @param key the cache entry key
-         * @param script the cache entry value
-         */
-        void put(K key, V script) {
-            Map<K, V> map = ref != null ? ref.get() : null;
-            if (map == null) {
-                map = createCache(size);
-                ref = new SoftReference<Map<K, V>>(map);
-            }
-            map.put(key, script);
-        }
-    }
-
-    /**
-     * Creates a cache.
-     * @param <K> the key type
-     * @param <V> the value type
-     * @param cacheSize the cache size, must be > 0
-     * @return a Map usable as a cache bounded to the given size
-     */
-    protected <K, V> Map<K, V> createCache(final int cacheSize) {
-        return new java.util.LinkedHashMap<K, V>(cacheSize, LOAD_FACTOR, true) {
-            /** Serial version UID. */
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
-                return size() > cacheSize;
-            }
-        };
-    }
-
-    /**
-     * Clears the expression cache.
-     */
-    public void clearCache() {
-        synchronized (parser) {
-            cache.clear();
-        }
-    }
-
-    /**
-     * Gets the list of variables accessed by a script.
-     * <p>This method will visit all nodes of a script and extract all variables whether they
-     * are written in 'dot' or 'bracketed' notation. (a.b is equivalent to a['b']).</p>
-     * @param script the script
-     * @return the set of variables, each as a list of strings (ant-ish variables use more than 1 string)
-     *         or the empty set if no variables are used
-     */
-    protected Set<List<String>> getVariables(JexlNode script) {
-        Set<List<String>> refs = new LinkedHashSet<List<String>>();
-        getVariables(script, refs, null);
-        return refs;
-    }
-
-    /**
-     * Fills up the list of variables accessed by a node.
-     * @param node the node
-     * @param refs the set of variable being filled
-     * @param ref the current variable being filled
-     */
-    protected void getVariables(JexlNode node, Set<List<String>> refs, List<String> ref) {
-        boolean array = node instanceof ASTArrayAccess;
-        boolean reference = node instanceof ASTReference;
-        int num = node.jjtGetNumChildren();
-        if (array || reference) {
-            List<String> var = ref != null ? ref : new ArrayList<String>();
-            boolean varf = true;
-            for (int i = 0; i < num; ++i) {
-                JexlNode child = node.jjtGetChild(i);
-                if (array) {
-                    if (child instanceof ASTReference && child.jjtGetNumChildren() == 1) {
-                        JexlNode desc = child.jjtGetChild(0);
-                        if (varf && desc.isConstant()) {
-                            String image = desc.image;
-                            if (image == null) {
-                                var.add(new Debugger().data(desc));
-                            } else {
-                                var.add(image); 
-                            }
-                        } else if (desc instanceof ASTIdentifier) {
-                            if (((ASTIdentifier) desc).getRegister() < 0) {
-                                List<String> di = new ArrayList<String>(1);
-                                di.add(desc.image);
-                                refs.add(di);
-                            }
-                            var = new ArrayList<String>();
-                            varf = false;
-                        }
-                        continue;
-                    } else if (child instanceof ASTIdentifier) {
-                        if (i == 0 && (((ASTIdentifier) child).getRegister() < 0)) {
-                            var.add(child.image);
-                        }
-                        continue;
-                    }
-                } else {//if (reference) {
-                    if (child instanceof ASTIdentifier) {
-                        if (((ASTIdentifier) child).getRegister() < 0) {
-                            var.add(child.image);
-                        }
-                        continue;
-                    }
-                }
-                getVariables(child, refs, var);
-            }
-            if (!var.isEmpty() && var != ref) {
-                refs.add(var);
-            }
-        } else {
-            for (int i = 0; i < num; ++i) {
-                getVariables(node.jjtGetChild(i), refs, null);
-            }
-        }
-    }
-
-    /**
-     * Gets the array of parameters from a script.
-     * @param script the script
-     * @return the parameters which may be empty (but not null) if no parameters were defined
-     * @since 3.0
-     */
-    protected String[] getParameters(JexlScript script) {
-        return script.getParameters();
-    }
-
-    /**
-     * Gets the array of local variable from a script.
-     * @param script the script
-     * @return the local variables array which may be empty (but not null) if no local variables were defined
-     * @since 3.0
-     */
-    protected String[] getLocalVariables(JexlScript script) {
-        return script.getLocalVariables();
-    }
-
-    /**
-     * A script scope, stores the declaration of parameters and local variables.
-     * @since 3.0
-     */
-    public static final class Scope {
-        /**
-         * The number of parameters.
-         */
-        protected final int parms;
-        /**
-         * The map of named registers aka script parameters.
-         * Each parameter is associated to a register and is materialized as an offset in the registers array used
-         * during evaluation.
-         */
-        protected Map<String, Integer> namedRegisters = null;
-
-        /**
-         * Creates a new scope with a list of parameters.
-         * @param parameters the list of parameters
-         */
-        public Scope(String... parameters) {
-            if (parameters != null) {
-                parms = parameters.length;
-                namedRegisters = new LinkedHashMap<String, Integer>();
-                for (int p = 0; p < parms; ++p) {
-                    namedRegisters.put(parameters[p], p);
-                }
-            } else {
-                parms = 0;
-            }
-        }
-
-        @Override
-        public int hashCode() {
-            return namedRegisters == null ? 0 : parms ^ namedRegisters.hashCode();
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            return o instanceof Scope && equals((Scope) o);
-        }
-
-        /**
-         * Whether this frame is equal to another.
-         * @param frame the frame to compare to
-         * @return true if equal, false otherwise
-         */
-        public boolean equals(Scope frame) {
-            if (this == frame) {
-                return true;
-            } else if (frame == null || parms != frame.parms) {
-                return false;
-            } else if (namedRegisters == null) {
-                return frame.namedRegisters == null;
-            } else {
-                return namedRegisters.equals(frame.namedRegisters);
-            }
-        }
-
-        /**
-         * Checks whether an identifier is a local variable or argument, ie stored in a register. 
-         * @param name the register name
-         * @return the register index
-         */
-        public Integer getRegister(String name) {
-            return namedRegisters != null ? namedRegisters.get(name) : null;
-        }
-
-        /**
-         * Declares a local variable.
-         * <p>
-         * This method creates an new entry in the named register map.
-         * </p>
-         * @param name the variable name
-         * @return the register index storing this variable
-         */
-        public Integer declareVariable(String name) {
-            if (namedRegisters == null) {
-                namedRegisters = new LinkedHashMap<String, Integer>();
-            }
-            Integer register = namedRegisters.get(name);
-            if (register == null) {
-                register = Integer.valueOf(namedRegisters.size());
-                namedRegisters.put(name, register);
-            }
-            return register;
-        }
-
-        /**
-         * Creates a frame by copying values up to the number of parameters.
-         * @param values the argument values
-         * @return the arguments array
-         */
-        public Frame createFrame(Object... values) {
-            if (namedRegisters != null) {
-                Object[] arguments = new Object[namedRegisters.size()];
-                if (values != null) {
-                    System.arraycopy(values, 0, arguments, 0, Math.min(parms, values.length));
-                }
-                return new Frame(arguments, namedRegisters.keySet().toArray(new String[0]));
-            } else {
-                return null;
-            }
-        }
-
-        /**
-         * Gets the (maximum) number of arguments this script expects.
-         * @return the number of parameters
-         */
-        public int getArgCount() {
-            return parms;
-        }
-
-        /**
-         * Gets this script registers, i.e. parameters and local variables.
-         * @return the register names
-         */
-        public String[] getRegisters() {
-            return namedRegisters != null ? namedRegisters.keySet().toArray(new String[0]) : new String[0];
-        }
-
-        /**
-         * Gets this script parameters, i.e. registers assigned before creating local variables.
-         * @return the parameter names
-         */
-        public String[] getParameters() {
-            if (namedRegisters != null && parms > 0) {
-                String[] pa = new String[parms];
-                int p = 0;
-                for (Map.Entry<String, Integer> entry : namedRegisters.entrySet()) {
-                    if (entry.getValue().intValue() < parms) {
-                        pa[p++] = entry.getKey();
-                    }
-                }
-                return pa;
-            } else {
-                return null;
-            }
-        }
-
-        /**
-         * Gets this script local variable, i.e. registers assigned to local variables.
-         * @return the parameter names
-         */
-        public String[] getLocalVariables() {
-            if (namedRegisters != null && parms > 0) {
-                String[] pa = new String[parms];
-                int p = 0;
-                for (Map.Entry<String, Integer> entry : namedRegisters.entrySet()) {
-                    if (entry.getValue().intValue() >= parms) {
-                        pa[p++] = entry.getKey();
-                    }
-                }
-                return pa;
-            } else {
-                return null;
-            }
-        }
-    }
-
-    /**
-     * A call frame, created from a scope, stores the arguments and local variables as "registers".
-     * @since 3.0
-     */
-    public static final class Frame {
-        /** Registers or arguments. */
-        protected Object[] registers = null;
-        /** Parameter and argument names if any. */
-        protected String[] parameters = null;
-        
-        /**
-         * Creates a new frame.
-         * @param r the registers
-         * @param p the parameters
-         */
-        Frame(Object[] r, String[] p) {
-            registers = r;
-            parameters = p;
-        }
-        
-        /**
-         * @return the registers
-         */
-        public Object[] getRegisters() {
-            return registers;
-        }
-                
-        /**
-         * @return the parameters
-         */
-        public String[] getParameters() {
-            return parameters;
-        }
-    }
-
-    /**
-     * Parses an expression.
-     * @param expression the expression to parse
-     * @param info debug information structure
-     * @param frame the script frame to use
-     * @return the parsed tree
-     * @throws JexlException if any error occured during parsing
-     */
-    protected ASTJexlScript parse(CharSequence expression, JexlInfo info, Scope frame) {
-        String expr = cleanExpression(expression);
-        ASTJexlScript script = null;
-        JexlInfo jexlInfo = null;
-        synchronized (parser) {
-            if (cache != null) {
-                script = cache.get(expr);
-                if (script != null) {
-                    Scope f = script.getScope();
-                    if ((f == null && frame == null) || (f != null && f.equals(frame))) {
-                        return script;
-                    }
-                }
-            }
-            try {
-                Reader reader = new StringReader(expr);
-                // use first calling method of JexlEngine as debug info
-                if (info == null) {
-                    jexlInfo = jexlInfo();
-                } else {
-                    jexlInfo = info;
-                }
-                parser.setFrame(frame);
-                script = parser.parse(reader, jexlInfo);
-                // reaccess in case local variables have been declared
-                frame = parser.getFrame();
-                if (frame != null) {
-                    script.setScope(frame);
-                }
-                if (cache != null) {
-                    cache.put(expr, script);
-                }
-            } catch (TokenMgrError xtme) {
-                throw new JexlException.Tokenization(jexlInfo, expression, xtme);
-            } catch (ParseException xparse) {
-                throw new JexlException.Parsing(jexlInfo, expression, xparse);
-            } finally {
-                parser.setFrame(null);
-            }
-        }
-        return script;
-    }
-
-    /**
-     * Creates a JexlInfo instance.
-     * @param fn url/file name
-     * @param l line number
-     * @param c column number
-     * @return a JexlInfo instance
-     */
-    protected JexlInfo createInfo(String fn, int l, int c) {
-        return new JexlInfo(fn, l, c);
-    }
-
-    /**
-     * Creates and fills up debugging information.
-     * <p>This gathers the class, method and line number of the first calling method
-     * not owned by JexlEngine, UnifiedJEXL or {Script,Expression}Factory.</p>
-     * @return an Info if debug is set, null otherwise
-     */
-    protected JexlInfo jexlInfo() {
-        JexlInfo info = null;
-        if (debug) {
-            Throwable xinfo = new Throwable();
-            xinfo.fillInStackTrace();
-            StackTraceElement[] stack = xinfo.getStackTrace();
-            StackTraceElement se = null;
-            Class<?> clazz = getClass();
-            for (int s = 1; s < stack.length; ++s, se = null) {
-                se = stack[s];
-                String className = se.getClassName();
-                if (!className.equals(clazz.getName())) {
-                    // go deeper if called from JexlEngine or UnifiedJEXL
-                    if (className.equals(JexlEngine.class.getName())) {
-                        clazz = JexlEngine.class;
-                    } else if (className.equals(UnifiedJEXL.class.getName())) {
-                        clazz = UnifiedJEXL.class;
-                    } else {
-                        break;
-                    }
-                }
-            }
-            if (se != null) {
-                info = createInfo(se.getClassName() + "." + se.getMethodName(), se.getLineNumber(), 0);
-            }
-        }
-        return info;
-    }
-
+    public abstract Object newInstance(String clazz, Object... args);
+    
     /**
      * Trims the expression from front & ending spaces.
      * @param str expression to clean

Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java?rev=1210927&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java Tue Dec  6 14:19:33 2011
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl3;
+
+import java.math.MathContext;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A JEXL evaluation context wrapping variables and options.
+ */
+public class JexlEvalContext implements JexlContext, JexlEngine.Options {
+    /** The marker for the empty vars. */
+    protected static final Map<String,Object> EMPTY_MAP = Collections.<String,Object>emptyMap();
+    /** The wrapped variable vars (if any).*/
+    protected final Map<String, Object> vars;
+    /** Whether the engine should be silent. */
+    private Boolean silent = null;
+    /** Whether the engine should be strict. */
+    private Boolean strict = null;
+    /** Whether the arithmetic should be strict. */
+    private Boolean astrict = null;
+    /** The namespaces vars the engine should use. */
+    private Map<String, Object> namespaces = null;
+    /** The math scale the arithmetic should use. */
+    private int mathScale = Integer.MIN_VALUE;
+    /** The math context the arithmetic should use. */
+    private MathContext mathContext = null;
+
+    /**
+     * Default constructor.
+     */
+    public JexlEvalContext() {
+        this(EMPTY_MAP);
+    }
+
+    /**
+     * Creates a MapContext wrapping an existing user provided vars.
+     * <p>The supplied vars should be null only in derived classes that override the get/set/has methods.
+     * For a default vars context with a code supplied vars, use the default no-parameter contructor.</p>
+     * @param vars the variable vars
+     */
+    public JexlEvalContext(Map<String, Object> vars) { 
+        this.vars = vars == EMPTY_MAP ? new HashMap<String, Object>() : vars;
+    }
+
+    @Override
+    public boolean has(String name) {
+        return vars.containsKey(name);
+    }
+
+    @Override
+    public Object get(String name) {
+        return vars.get(name);
+    }
+
+    @Override
+    public void set(String name, Object value) {
+        vars.put(name, value);
+    }
+
+    /**
+     * Clears the variable vars.
+     */
+    public void clearVariables() {
+        vars.clear();
+    }
+
+    /**
+     * Clear all options.
+     */
+    public void clearOptions() {
+        silent = null;
+        strict = null;
+        namespaces = null;
+        mathScale = -1;
+        mathContext = null;
+    }
+
+    /**
+     * Sets whether the engine will throw JexlException during evaluation when an error is triggered.
+     * @param s true means no JexlException will occur, false allows them
+     */
+    public void setSilent(boolean s) {
+        this.silent = s ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    @Override
+    public Boolean isSilent() {
+        return this.silent;
+    }
+
+    /**
+     * Sets the engine and arithmetic strict flags in one call.
+     * @param se the engine strict flag
+     * @param sa the arithmetic strict flag
+     */
+    public void setStrict(boolean se, boolean sa) {
+        this.strict = se ? Boolean.TRUE : Boolean.FALSE;
+        this.astrict = sa ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    /**
+     * Sets whether the engine will consider unknown variables, methods and constructors as errors or evaluates them
+     * as null.
+     * @param se true means strict error reporting, false allows mentioned conditions to be evaluated as null
+     */
+    public void setStrict(boolean se) {
+        setStrict(se, se);
+    }
+
+    @Override
+    public Boolean isStrict() {
+        if (strict == null) {
+            return null;
+        } else {
+            return strict.booleanValue() ? Boolean.TRUE : Boolean.FALSE;
+        }
+    }
+
+    /**
+     * Sets whether the arithmetic will consider null arguments as errors during evaluation.
+     * @param s true means strict error reporting, false allows mentioned conditions to be evaluated as 0
+     */
+    public void setStrictArithmetic(boolean s) {
+        this.astrict = s ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    @Override
+    public Boolean isStrictArithmetic() {
+        if (astrict == null) {
+            return null;
+        } else {
+            return astrict.booleanValue() ? Boolean.TRUE : Boolean.FALSE;
+        }
+    }
+
+    @Override
+    public MathContext getArithmeticMathContext() {
+        return mathContext;
+    }
+
+    /**
+     * Sets the {@link MathContext} to use by the {@link JexlArithmetic} during evaluation.
+     * @param mc the math context
+     */
+    public void setMathContext(MathContext mc) {
+        mathContext = mc;
+    }
+
+    @Override
+    public int getArithmeticMathScale() {
+        return mathScale;
+    }
+
+    /**
+     * Sets the math scale to use to use by the {@link JexlArithmetic} during evaluation.
+     * @param scale the math scale
+     */
+    public void setMathScale(int scale) {
+        mathScale = scale;
+    }
+
+    @Override
+    public Map<String, Object> getNamespaces() {
+        return namespaces;
+    }
+
+    /**
+     * Sets the namespaces vars to use during evaluation.
+     * @param funcs the namespaces
+     */
+    public void setNamespaces(Map<String, Object> funcs) {
+        namespaces = funcs;
+    }
+}

Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlEvalContext.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message