You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2009/12/18 16:33:14 UTC
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/
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 {