commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hen...@apache.org
Subject svn commit: r892278 - in /commons/proper/jexl/trunk: ./ src/main/java/org/apache/commons/jexl2/ src/main/java/org/apache/commons/jexl2/parser/ src/main/java/org/apache/commons/jexl2/scripting/ src/test/java/org/apache/commons/jexl2/scripting/
Date Fri, 18 Dec 2009 15:33:14 GMT
Author: henrib
Date: Fri Dec 18 15:33:11 2009
New Revision: 892278

URL: http://svn.apache.org/viewvc?rev=892278&view=rev
Log:
JEXL-95 fix

Added:
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineOptionalTest.java
  (with props)
Modified:
    commons/proper/jexl/trunk/pom.xml
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlEngine.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/StringParser.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/scripting/JexlScriptEngine.java
    commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/scripting/JexlScriptEngineFactory.java
    commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineTest.java

Modified: commons/proper/jexl/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/pom.xml?rev=892278&r1=892277&r2=892278&view=diff
==============================================================================
--- commons/proper/jexl/trunk/pom.xml (original)
+++ commons/proper/jexl/trunk/pom.xml Fri Dec 18 15:33:11 2009
@@ -106,7 +106,7 @@
         <dependency>
             <groupId>org.apache.bsf</groupId>
             <artifactId>bsf-api</artifactId>
-            <version>3.0-beta3</version>
+            <version>[3.0-beta3,)</version>
             <scope>compile</scope>
         </dependency>
     </dependencies>

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlEngine.java?rev=892278&r1=892277&r2=892278&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlEngine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlEngine.java Fri Dec
18 15:33:11 2009
@@ -872,7 +872,7 @@
      * @param str expression to clean
      * @return trimmed expression ending in a semi-colon
      */
-    protected String cleanExpression(CharSequence str) {
+    public static final String cleanExpression(CharSequence str) {
         if (str != null) {
             int start = 0;
             int end = str.length();
@@ -893,15 +893,20 @@
     }
 
     /**
-     * Read a buffered reader into a StringBuffer and return a String with
+     * Read from a reader into a StringBuffer and return a String with
      * the contents of the reader.
-     * @param reader to be read.
+     * @param scriptReader to be read.
      * @return the contents of the reader as a String.
      * @throws IOException on any error reading the reader.
      */
-    protected static String readerToString(BufferedReader reader)
-            throws IOException {
+    public static final String readerToString(Reader scriptReader) throws IOException {
         StringBuilder buffer = new StringBuilder();
+        BufferedReader reader;
+        if (scriptReader instanceof BufferedReader) {
+            reader = (BufferedReader) scriptReader;
+        } else {
+            reader = new BufferedReader(scriptReader);
+        }
         try {
             String line;
             while ((line = reader.readLine()) != null) {
@@ -909,7 +914,11 @@
             }
             return buffer.toString();
         } finally {
-            reader.close();
+            try {
+                reader.close();
+            } catch(IOException xio) {
+                // ignore
+            }
         }
 
     }

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/StringParser.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/StringParser.java?rev=892278&r1=892277&r2=892278&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/StringParser.java
(original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/StringParser.java
Fri Dec 18 15:33:11 2009
@@ -34,6 +34,9 @@
  * </p>
  */
 public class StringParser {
+    /** Default constructor.  */
+    public StringParser() {}
+    
     /**
      * Builds a string, handles escaping through '\' syntax.
      * @param str the string to build from
@@ -135,4 +138,45 @@
         strb.append(xc);
         return 4;
     }
+    
+    /**
+     * Escapes a String representation, expand non-ASCII characters as Unicode escape sequence.
+     * @param str the string to escape
+     * @return the escaped representation
+     */
+    public static String escapeString(String str) {
+        if (str == null) {
+            return null;
+        }
+        final int length = str.length();
+        StringBuilder strb = new StringBuilder(length + 2);
+        strb.append('\'');
+        for (int i = 0; i < length; ++i) {
+            char c = str.charAt(i);
+            if (c < 127) {
+                if (c == '\'') {
+                    // escape quote
+                    strb.append('\\');
+                    strb.append('\'');
+                } else if (c == '\\') {
+                    // escape backslash
+                    strb.append('\\');
+                    strb.append('\\');
+                } else {
+                    strb.append(c);
+                }
+            } else {
+                // convert to Unicode escape sequence
+                strb.append('\\');
+                strb.append('u');
+                String hex = Integer.toHexString(c);
+                for (int h = hex.length(); h < 4; ++h) {
+                    strb.append('0');
+                }
+                strb.append(hex);
+            }
+        }
+        strb.append('\'');
+        return strb.toString();
+    }
 }
\ No newline at end of file

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/scripting/JexlScriptEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/scripting/JexlScriptEngine.java?rev=892278&r1=892277&r2=892278&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/scripting/JexlScriptEngine.java
(original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/scripting/JexlScriptEngine.java
Fri Dec 18 15:33:11 2009
@@ -17,13 +17,17 @@
 
 package org.apache.commons.jexl2.scripting;
 
-import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.Reader;
+import java.util.HashMap;
+import java.util.Map;
 
 import javax.script.AbstractScriptEngine;
 import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
 import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
 import javax.script.ScriptException;
 import javax.script.SimpleBindings;
@@ -51,7 +55,7 @@
  * Javadoc.
  * @since 2.0
  */
-public class JexlScriptEngine extends AbstractScriptEngine {
+public class JexlScriptEngine extends AbstractScriptEngine implements Compilable {
 
     /** Reserved key for JexlScriptObject. */
     public static final String JEXL_OBJECT_KEY = "JEXL";
@@ -64,7 +68,7 @@
     
     /** The JEXL EL engine. */
     private final JexlEngine jexlEngine;
-    
+   
     /**
      * Default constructor.
      * <p>
@@ -76,6 +80,19 @@
     }
 
     /**
+     * The set of functions exposed in the default namespace.
+     */
+    public static final class JexlFunctions {
+        /**
+         * Calls System.out.println.
+         * @param arg the argument
+         */
+        public void print(String arg) {
+            System.out.println(arg);
+        }
+    }
+    
+    /**
      * Create a scripting engine using the supplied factory.
      * 
      * @param factory the factory which created this instance.
@@ -87,6 +104,10 @@
         }
         parentFactory = factory;
         jexlEngine = new JexlEngine();
+        // Add the jexl functions, ie print and escape
+        Map<String,Object> funcs = new HashMap<String,Object>();
+        funcs.put(null, new JexlFunctions());
+        jexlEngine.setFunctions(funcs);
         // Add utility object
         put(JEXL_OBJECT_KEY, new JexlScriptObject());
     }
@@ -97,45 +118,28 @@
     }
 
     /** {@inheritDoc} */
-    public Object eval(Reader script, ScriptContext context) throws ScriptException {
+    public Object eval(Reader reader, ScriptContext context) throws ScriptException {
         // This is mandated by JSR-223 (see SCR.5.5.2   Methods)
-        if (script == null || context == null) {
+        if (reader == null || context == null) {
             throw new NullPointerException("script and context must be non-null");
         }
-        BufferedReader reader = new BufferedReader(script);
-        StringBuilder buffer = new StringBuilder();
-        try {
-            String line;
-            try {
-                while ((line = reader.readLine()) != null) {
-                    buffer.append(line).append('\n');
-                }
-            } catch (IOException e) {
-                throw new ScriptException(e);
-            }
-        } finally {
-            try {
-                reader.close();
-            } catch (IOException e) {
-                // NOOP
-            }
-        }
-        return eval(buffer.toString(), context);
+
+        return eval(readerToString(reader), context);
     }
 
     /** {@inheritDoc} */
-    public Object eval(String scriptText, final ScriptContext context) throws ScriptException
{
+    public Object eval(String script, final ScriptContext context) throws ScriptException
{
         // This is mandated by JSR-223 (see SCR.5.5.2   Methods)
-        if (scriptText == null || context == null) {
+        if (script == null || context == null) {
             throw new NullPointerException("script and context must be non-null");
         }
         // This is mandated by JSR-223 (end of section SCR.4.3.4.1.2 - Script Execution)
         context.setAttribute(CONTEXT_KEY, context, ScriptContext.ENGINE_SCOPE);
         
         try {
-            Script script = jexlEngine.createScript(scriptText);
+            Script jexlScript = jexlEngine.createScript(script);
             JexlContext ctxt = new JexlContextWrapper(context);
-            return script.execute(ctxt);
+            return jexlScript.execute(ctxt);
         } catch (Exception e) {
             throw new ScriptException(e.toString());
         }
@@ -146,10 +150,49 @@
         return parentFactory;
     }
 
+    /** {@inheritDoc} */
+    public CompiledScript compile(String script) throws ScriptException {
+        // This is mandated by JSR-223
+        if (script == null) {
+            throw new NullPointerException("script must be non-null");
+        }
+        try {
+            Script jexlScript = jexlEngine.createScript(script);
+            return new JexlCompiledScript(jexlScript);
+        } catch (Exception e) {
+            throw new ScriptException(e.toString());
+        }
+    }
+
+    /** {@inheritDoc} */
+    public CompiledScript compile(Reader script) throws ScriptException {
+        // This is mandated by JSR-223
+        if (script == null) {
+            throw new NullPointerException("script must be non-null");
+        }
+        return compile(readerToString(script));
+    }
+
+    /**
+     * Reads a script.
+     * @param script the script reader
+     * @return the script as a string
+     * @throws ScriptException if an exception occurs during read
+     */
+    private String readerToString(Reader script) throws ScriptException {
+        try {
+           return JexlEngine.readerToString(script);
+        } catch (IOException e) {
+            throw new ScriptException(e);
+        }
+    }
+
     /**
      * Holds singleton JexlScriptEngineFactory (IODH). 
      */
     private static class SingletonHolder {
+        /** non instantiable. */
+        private SingletonHolder() {}
         /** The singleton instance. */
         private static final JexlScriptEngineFactory DEFAULT_FACTORY = new JexlScriptEngineFactory();
     }
@@ -159,7 +202,7 @@
      *
      * Current implementation only gives access to ENGINE_SCOPE binding.
      */
-    private static class JexlContextWrapper implements JexlContext {
+    private static final class JexlContextWrapper implements JexlContext {
         /** The engine context. */
         private final ScriptContext engineContext;
         /**
@@ -192,4 +235,47 @@
         }
 
     }
+
+    /**
+     * Wrapper to help convert a Jexl Script into a JSR-223 CompiledScript.
+     */
+    private final class JexlCompiledScript extends CompiledScript {
+        /** The underlying Jexl expression instance. */
+        private final Script script;
+
+        /**
+         * Creates an instance.
+         * @param theScript to wrap
+         */
+        private JexlCompiledScript(Script theScript) {
+            script = theScript;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public String toString() {
+            return script.getText();
+        }
+        
+        /** {@inheritDoc} */
+        @Override
+        public Object eval(ScriptContext context) throws ScriptException {
+            // This is mandated by JSR-223 (end of section SCR.4.3.4.1.2 - Script Execution)
+            context.setAttribute(CONTEXT_KEY, context, ScriptContext.ENGINE_SCOPE);
+            try {
+                JexlContext ctxt = new JexlContextWrapper(context);
+                return script.execute(ctxt);
+            } catch (Exception e) {
+                throw new ScriptException(e.toString());
+            }
+        }
+        
+        /** {@inheritDoc} */
+        @Override
+        public ScriptEngine getEngine() {
+            return JexlScriptEngine.this;
+        }
+    }
+
+
 }

Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/scripting/JexlScriptEngineFactory.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/scripting/JexlScriptEngineFactory.java?rev=892278&r1=892277&r2=892278&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/scripting/JexlScriptEngineFactory.java
(original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/scripting/JexlScriptEngineFactory.java
Fri Dec 18 15:33:11 2009
@@ -23,6 +23,8 @@
 
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
+import org.apache.commons.jexl2.JexlEngine;
+import org.apache.commons.jexl2.parser.StringParser;
 
 /**
  * Implements the Jexl ScriptEngineFactory for JSF-223.
@@ -60,11 +62,11 @@
     }
 
     /** {@inheritDoc} */
-    public String getMethodCallSyntax(String object, String method, String[] args) {
+    public String getMethodCallSyntax(String obj, String m, String... args) {
         StringBuilder sb = new StringBuilder();
-        sb.append(object);
+        sb.append(obj);
         sb.append('.');
-        sb.append(method);
+        sb.append(m);
         sb.append('(');
         boolean needComma = false;
         for(String arg : args){
@@ -94,8 +96,12 @@
     }
 
     /** {@inheritDoc} */
-    public String getOutputStatement(String message) {  // TODO - is there one?
-        throw new UnsupportedOperationException("Not yet implemented");
+    public String getOutputStatement(String toDisplay) {
+        if (toDisplay == null) {
+            return "print(null)";
+        } else {
+            return "print("+StringParser.escapeString(toDisplay)+")";
+        }
     }
 
     /** {@inheritDoc} */
@@ -117,11 +123,11 @@
     }
 
     /** {@inheritDoc} */
-    public String getProgram(String[] args) {
+    public String getProgram(String... statements) {
         StringBuilder sb = new StringBuilder();
-        for(String arg : args){
-            sb.append(arg);
-            if (!arg.endsWith(";")){
+        for(String statement : statements){
+            sb.append(JexlEngine.cleanExpression(statement));
+            if (!statement.endsWith(";")){
                 sb.append(';');
             }
         }

Added: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineOptionalTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineOptionalTest.java?rev=892278&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineOptionalTest.java
(added)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineOptionalTest.java
Fri Dec 18 15:33:11 2009
@@ -0,0 +1,57 @@
+/*
+ * 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.jexl2.scripting;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import junit.framework.TestCase;
+
+public class JexlScriptEngineOptionalTest extends TestCase {
+    private final JexlScriptEngineFactory factory = new JexlScriptEngineFactory();
+    private final ScriptEngineManager manager = new ScriptEngineManager();
+    private final ScriptEngine engine = manager.getEngineByName("jexl");
+
+    public void testScriptEngineOutput() throws Exception {
+        String output = factory.getOutputStatement("foo\u00a9bar");
+        assertEquals(output, "print('foo\\u00a9bar')");
+        // redirect output to capture evaluation result
+        final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        try {
+            engine.eval(output);
+        } finally {
+            System.setOut(null);
+        }
+        assertEquals("foo\u00a9bar\n", outContent.toString());
+    }
+
+    public void testCompilable() throws Exception {
+        assertTrue("Engine should implement Compilable", engine instanceof Compilable);
+        Compilable cengine = (Compilable) engine;
+        CompiledScript script = cengine.compile("40 + 2");
+        assertEquals(Integer.valueOf(42), script.eval());
+        assertEquals(Integer.valueOf(42), script.eval());
+    }
+
+}

Propchange: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineOptionalTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineTest.java?rev=892278&r1=892277&r2=892278&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineTest.java
(original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/scripting/JexlScriptEngineTest.java
Fri Dec 18 15:33:11 2009
@@ -18,9 +18,13 @@
 
 package org.apache.commons.jexl2.scripting;
 
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
 import java.io.Reader;
 import java.util.Arrays;
 import java.util.Map;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
 
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineManager;
@@ -42,10 +46,6 @@
 
         assertEquals("42;", factory.getProgram(new String[]{"42"}));
         assertEquals("str.substring(3,4)", factory.getMethodCallSyntax("str", "substring",
new String[]{"3", "4"}));
-        try {
-            factory.getOutputStatement("foo");
-            fail("getOutputStatement() should have thrown");
-        } catch(Exception xignore) {}
     }
 
     public void testScripting() throws Exception {



Mime
View raw message