Repository: incubator-tamaya-sandbox
Updated Branches:
  refs/heads/master 855230b79 -> 9731be7d5


TAMAYA-145: Using beanshell for expression evaluation.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/commit/9731be7d
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/tree/9731be7d
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/diff/9731be7d

Branch: refs/heads/master
Commit: 9731be7d5cd6192ab4337da53c741601f7132362
Parents: 855230b
Author: anatole <anat...@apache.org>
Authored: Mon May 1 22:23:11 2017 +0200
Committer: anatole <anat...@apache.org>
Committed: Mon May 1 22:23:29 2017 +0200

----------------------------------------------------------------------
 metamodel/pom.xml                               |   5 +
 .../tamaya/metamodel/EnabledPropertySource.java |  23 +---
 .../internal/resolver/JavaResolver.java         | 124 ++++++++++++-------
 .../internal/resolver/JavaResolverTest.java     |  52 +++++---
 metamodel/src/test/resources/tamaya-config.xml  |  13 +-
 5 files changed, 132 insertions(+), 85 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/9731be7d/metamodel/pom.xml
----------------------------------------------------------------------
diff --git a/metamodel/pom.xml b/metamodel/pom.xml
index 0cfc48d..bfffea8 100644
--- a/metamodel/pom.xml
+++ b/metamodel/pom.xml
@@ -78,6 +78,11 @@
             <scope>provided</scope>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>org.apache-extras.beanshell</groupId>
+            <artifactId>bsh</artifactId>
+            <version>2.0b6</version>
+        </dependency>
         <!--<dependency>-->
             <!--<groupId>org.apache.tamaya.ext</groupId>-->
             <!--<artifactId>tamaya-json</artifactId>-->

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/9731be7d/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySource.java
----------------------------------------------------------------------
diff --git 
a/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySource.java
 
b/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySource.java
index 7e04499..2dcf101 100644
--- 
a/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySource.java
+++ 
b/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySource.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tamaya.metamodel;
 
+import org.apache.tamaya.metamodel.internal.resolver.JavaResolver;
 import org.apache.tamaya.spi.PropertySource;
 import org.apache.tamaya.spi.PropertyValue;
 import org.apache.tamaya.spisupport.PropertySourceComparator;
@@ -42,6 +43,7 @@ public final class EnabledPropertySource
     private String enabledExpression;
     private PropertySource wrapped;
     private boolean enabled;
+    private static final JavaResolver resolver = new JavaResolver();
 
     public EnabledPropertySource(PropertySource wrapped, Map<String,String> 
context, String expression) {
         this.enabledExpression = Objects.requireNonNull(expression);
@@ -51,25 +53,8 @@ public final class EnabledPropertySource
 
     protected boolean calculateEnabled(Map<String, String> context) {
         try {
-            ScriptEngineManager manager = new ScriptEngineManager();
-            ScriptEngine engine = manager.getEngineByName("nashorn");
-            if(engine==null){
-                engine = manager.getEngineByName("rhino");
-            }
-            // init script engine
-            for(Map.Entry<String,String> entry: context.entrySet()) {
-                engine.put(entry.getKey(), entry.getValue());
-            }
-            Object o = engine.eval(enabledExpression);
-            if(!(o instanceof Boolean)){
-                LOG.severe("Enabled expression must evaluate to Boolean: '"
-                        +enabledExpression+"', but was " + o +
-                        ", property source will be disabled: " +
-                        wrapped.getName());
-                return false;
-            }
-            return (Boolean)o;
-        } catch (ScriptException e) {
+            return Boolean.TRUE.equals(resolver.evaluate(enabledExpression, 
context));
+        } catch (Exception e) {
             LOG.severe("Invalid Boolean expression: '"
                     +enabledExpression+"': " + e + ", property source will be 
disabled: " +
                     wrapped.getName());

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/9731be7d/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/resolver/JavaResolver.java
----------------------------------------------------------------------
diff --git 
a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/resolver/JavaResolver.java
 
b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/resolver/JavaResolver.java
index 22d8618..2739da9 100644
--- 
a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/resolver/JavaResolver.java
+++ 
b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/resolver/JavaResolver.java
@@ -18,28 +18,30 @@
  */
 package org.apache.tamaya.metamodel.internal.resolver;
 
+import bsh.*;
 import org.apache.tamaya.metamodel.MetaContext;
 import org.apache.tamaya.metamodel.spi.SimpleResolver;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Objects;
+import java.io.*;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * Simple resolver for {@link MetaContext} entries that
- * reads data from system and environment properties.
+ * reads data from system and environment properties and uses
+ * beanshell evaluation.
  *
  * Valid inputs are:
  * <ul>
- *     <li>{@code ${properties:sys:key?default=abcval} } reading a system 
property.</li>
- *     <li>{@code ${properties:env:key?default=abcval} } reading a environment 
property.</li>
- *     <li>{@code ${properties:ctx:[ctxName:]key?default=abcval} } reading a 
<i>default</i> MetaContext entry.</li>
+ *     <li>{@code ${java:expression} }, whereas <i>expression</i> evaluates to 
the required type.</li>
  * </ul>
- *
- * Hereby the _default_ parameter defines the default value to be applied, if 
no value was found.
  */
 public final class JavaResolver implements SimpleResolver{
+
+    private static final Logger LOG = 
Logger.getLogger(JavaResolver.class.getName());
+
+
     @Override
     public String getResolverId() {
         return "java";
@@ -47,45 +49,81 @@ public final class JavaResolver implements SimpleResolver{
 
     @Override
     public String evaluate(String expression) {
-        String[] mainParts = expression.split("#");
-        if(mainParts.length<2){
-            return null;
-        }else{
-            try {
-                return evaluate(mainParts[0].trim(), mainParts[1].trim());
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
+        try{
+            return String.valueOf(evaluate(expression, null));
+        }catch(Exception e){
+            LOG.log(Level.WARNING, "Error evaluating expression: " + 
expression, e);
+            return "ERROR{"+expression+"}:"+e;
         }
-        return null;
     }
 
-    private String evaluate(String className, String memberName) throws 
Exception{
-        Objects.requireNonNull(className);
-        Objects.requireNonNull(memberName);
-        Class clazz = Class.forName(className);
-        try {
-            Method method = clazz.getDeclaredMethod(memberName);
-            if (Modifier.isStatic(method.getModifiers())) {
-                if (!method.isAccessible()) {
-                    method.setAccessible(true);
+    public Object evaluate(String expression, Map<String, String> context) 
throws UtilEvalError, EvalError {
+            BshClassManager bshClassManager = new BshClassManager();
+            NameSpace namespace = new NameSpace(bshClassManager, "config");
+            namespace.loadDefaultImports();
+            namespace.importStatic(JavaResolver.class);
+            namespace.setVariable("contextprops", MetaContext.getInstance(), 
false);
+            namespace.setVariable("envprops", System.getenv(), false);
+            namespace.setVariable("sysprops", System.getProperties(), false);
+            if(context!=null){
+                for(Map.Entry<String,String> en:context.entrySet()){
+                    namespace.setVariable(en.getKey(), en.getValue(), false);
                 }
-                return (String) method.invoke(null);
             }
-        }catch(Exception e){
-            // ignore
-        }
-        try {
-            Field field = clazz.getDeclaredField(memberName);
-            if (Modifier.isStatic(field.getModifiers())) {
-                if (!field.isAccessible()) {
-                    field.setAccessible(true);
-                }
-                return (String) field.get(null);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            PrintStream outStream = new PrintStream(out);
+            ByteArrayOutputStream err = new ByteArrayOutputStream();
+            PrintStream errStream = new PrintStream(err);
+            Interpreter interpreter = new Interpreter(null,
+//                    new BufferedReader(
+//                    new InputStreamReader(System.in)),
+                    outStream, errStream,
+                    false, namespace);
+            return interpreter.eval(expression);
+    }
+
+    public static String context(String key){
+        return MetaContext.getInstance().getProperty(key);
+    }
+
+    public static String env(String key){
+        return System.getenv(key);
+    }
+
+    public static String sys(String key){
+        return System.getProperty(key);
+    }
+
+    public static long TIME(){
+        return System.currentTimeMillis();
+    }
+
+    public static Object[] eval(String command) throws IOException {
+        Process proc = Runtime.getRuntime().exec(command);
+        try(InputStream out = proc.getInputStream();
+            InputStream err = proc.getErrorStream()){
+            Object[] result = new Object[3];
+            ByteArrayOutputStream sw = new ByteArrayOutputStream();
+            byte[] buff = new byte[512];
+            result[0] = proc.waitFor();
+            int read = out.read(buff);
+            while(read > 0){
+                sw.write(buff, 0, read);
+                out.read(buff);
             }
-        }catch(Exception e){
-            // ignore
+            result[1] = sw.toString();
+            read = err.read(buff);
+            while(read > 0){
+                sw.write(buff, 0, read);
+                err.read(buff);
+            }
+            result[2] = sw.toString();
+            return result;
+        } catch (InterruptedException e) {
+            return new Object[]{"","Process interrupted.", -1};
+        } catch (Exception e){
+            return new Object[]{"","Process failed: " + e, -1};
         }
-        return null;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/9731be7d/metamodel/src/test/java/org/apache/tamaya/metamodel/internal/resolver/JavaResolverTest.java
----------------------------------------------------------------------
diff --git 
a/metamodel/src/test/java/org/apache/tamaya/metamodel/internal/resolver/JavaResolverTest.java
 
b/metamodel/src/test/java/org/apache/tamaya/metamodel/internal/resolver/JavaResolverTest.java
index 55ca290..0c1bfb3 100644
--- 
a/metamodel/src/test/java/org/apache/tamaya/metamodel/internal/resolver/JavaResolverTest.java
+++ 
b/metamodel/src/test/java/org/apache/tamaya/metamodel/internal/resolver/JavaResolverTest.java
@@ -18,9 +18,10 @@
  */
 package org.apache.tamaya.metamodel.internal.resolver;
 
+import org.apache.tamaya.metamodel.MetaContext;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 
 /**
@@ -28,7 +29,8 @@ import static org.junit.Assert.*;
  */
 public class JavaResolverTest {
 
-    private static final String TEST = "ResTest";
+    public static final String TEST = "ResTest";
+
     private JavaResolver r = new JavaResolver();
 
     @Test
@@ -37,34 +39,46 @@ public class JavaResolverTest {
     }
 
     @Test
-    public void evaluate() throws Exception {
-        assertEquals(TEST, 
r.evaluate("org.apache.tamaya.metamodel.internal.resolver.JavaResolverTest#TEST"));
-        assertEquals(TEST, 
r.evaluate("org.apache.tamaya.metamodel.internal.resolver.JavaResolverTest#getTest4"));
-        assertEquals(TEST, 
r.evaluate("org.apache.tamaya.metamodel.internal.resolver.JavaResolverTest#getTest6"));
-        assertEquals(TEST, 
r.evaluate("org.apache.tamaya.metamodel.internal.resolver.JavaResolverTest#getTest7"));
+    public void evaluateDirect() throws Exception {
+        assertEquals("value", r.evaluate("\"value\""));
+        assertEquals("1.1", r.evaluate("1.1"));
+        assertEquals("1", r.evaluate("1"));
     }
 
-    private String getTest5(){
-        return TEST;
-    }
-
-    String getTest2(){
-        return TEST;
+    @Test
+    public void evaluateProperties() throws Exception {
+        assertEquals(System.getProperty("java.version"), 
r.evaluate("sys(\"java.version\")"));
+        String key = System.getenv().keySet().iterator().next();
+        assertEquals(System.getenv(key), r.evaluate("env(\""+key+"\")"));
+        MetaContext.getInstance().setProperty("foo", "bar");
+        assertEquals("bar", r.evaluate("context(\"foo\")"));
     }
 
-    public String getTest3(){
-        return TEST;
+    @Test
+    public void evaluateExpression() throws Exception {
+        assertEquals("true", r.evaluate("env(\"STAGE\") == null"));
+        assertEquals("true", r.evaluate("sys(\"STAGE\") == null"));
+        System.setProperty("STAGE", "DEV2");
+        assertEquals("false", r.evaluate("sys(\"STAGE\") == null"));
+        System.setProperty("STAGE", "DEV2");
+        assertEquals("DEV2", r.evaluate("sys(\"STAGE\") == 
null?env(\"STAGE\"):sys(\"STAGE\")"));
+        assertEquals("DEV2", r.evaluate("if(sys(\"STAGE\") == null)return 
env(\"STAGE\"); else return sys(\"STAGE\");"));
+        System.getProperties().remove("STAGE");
+        assertEquals("foo", r.evaluate("if(sys(\"STAGE\") == null)return 
\"foo\"; else return sys(\"STAGE\");"));
     }
 
-    static String getTest4(){
-        return TEST;
+    @Test
+    public void evaluateSimple() throws Exception {
+        assertEquals(TEST, 
r.evaluate("org.apache.tamaya.metamodel.internal.resolver.JavaResolverTest.TEST"));
+        assertEquals(TEST, r.evaluate("new 
org.apache.tamaya.metamodel.internal.resolver.JavaResolverTest().getTest1()"));
+        assertEquals(TEST, 
r.evaluate("org.apache.tamaya.metamodel.internal.resolver.JavaResolverTest.getTest2()"));
     }
 
-    private static String getTest6(){
+    public String getTest1(){
         return TEST;
     }
 
-    public static String getTest7(){
+    public static String getTest2(){
         return TEST;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/9731be7d/metamodel/src/test/resources/tamaya-config.xml
----------------------------------------------------------------------
diff --git a/metamodel/src/test/resources/tamaya-config.xml 
b/metamodel/src/test/resources/tamaya-config.xml
index 388d84c..bdb3269 100644
--- a/metamodel/src/test/resources/tamaya-config.xml
+++ b/metamodel/src/test/resources/tamaya-config.xml
@@ -22,7 +22,7 @@
         <stage>${properties:system:STAGE?default=DEV}</stage>
         <configdir>${properties:system:configdir?default=.}</configdir>
         <app>${properties:system.APP?default=NONE}</app>
-        <context>${java:org.apache.tamaya.context.Context#id()}</context>
+        <context>${java:java.util.UUID.randomUUID()}</context>
         <company>Trivadis</company>
         <default-formats>yaml,json</default-formats>
         <default-refresh-period>5 SECOND</default-refresh-period>
@@ -36,7 +36,7 @@
     <!-- Configuration definition. -->
 
     <property-sources>
-       <env-properties enabled="${stage=TEST || stage=PTA || stage=PROD}">
+       <env-properties enabled="${context('stage')=='TEST' || 
context('stage')=='PTA' || context('stage')=='PROD'}">
            <filters>
                <Map target="ENV."/>
                <Mask policy="MULTIVALUE"
@@ -53,8 +53,8 @@
        <file location="config.xml" formats="xml-properties" refreshable="true" 
/>
        <resource location="/META-INF/application-config.yml"/>
        <ch.mypack.MyClassSource />
-       <!--<include enabled="${stage==TEST}">TEST-config.xml</include>-->
-       <resources location="${configdir}/**/*.json" enabled="${configdir != 
null}" />
+       <!--<include 
enabled="${CONTEXT('stage')==TEST}">TEST-config.xml</include>-->
+       <resources location="${context('configdir')}/**/*.json" 
enabled="${context('configdir') != null}" />
        <url location="https://www.confdrive.com/cfg/customerId=1234";
             formats="json"
             refreshable="true">
@@ -72,5 +72,10 @@
         <default-converters/>
     </property-converters>
 
+    <log>
+        "METACONTEXT: " + MetaContext.getInstance().getProperties()
+        "CONFIG     : " + Configuration.getInstance().getProperties()
+    </log>
+
 </configuration>
 

Reply via email to