This is an automated email from the ASF dual-hosted git repository.

chengzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 9f41f124ec1 Refactor EspressoInlineExpressionParser to use Truffle 
Context with life cycle (#30398)
9f41f124ec1 is described below

commit 9f41f124ec1470fb3ee9423cdb70a54660a47db3
Author: Ling Hengqian <[email protected]>
AuthorDate: Wed Mar 6 06:20:04 2024 +0800

    Refactor EspressoInlineExpressionParser to use Truffle Context with life 
cycle (#30398)
---
 distribution/proxy/src/main/release-docs/LICENSE   |  2 +-
 infra/expr/type/espresso/pom.xml                   |  6 ---
 .../espresso/EspressoInlineExpressionParser.java   | 39 +++++++++--------
 .../infra/expr/espresso/ReflectContext.java        | 10 ++++-
 .../infra/expr/espresso/ReflectValue.java          |  4 +-
 .../EspressoInlineExpressionParserTest.java        | 49 ++++++++++------------
 pom.xml                                            |  2 +-
 7 files changed, 56 insertions(+), 56 deletions(-)

diff --git a/distribution/proxy/src/main/release-docs/LICENSE 
b/distribution/proxy/src/main/release-docs/LICENSE
index 8ce7cb4f8a9..a729c926daa 100644
--- a/distribution/proxy/src/main/release-docs/LICENSE
+++ b/distribution/proxy/src/main/release-docs/LICENSE
@@ -240,7 +240,7 @@ The text of each license is the standard Apache 2.0 license.
     failsafe 2.4.4: https://github.com/jhalterman/failsafe, Apache 2.0
     failureaccess 1.0.1: https://github.com/google/guava, Apache 2.0
     freemarker 2.3.31: https://freemarker.apache.org/, Apache 2.0
-    groovy 4.0.10: https://groovy.apache.org/, Apache 2.0
+    groovy 4.0.19: https://groovy.apache.org/, Apache 2.0
     grpc-api 1.58.0: https://github.com/grpc/grpc-java, Apache 2.0
     grpc-context 1.58.0: https://github.com/grpc/grpc-java, Apache 2.0
     grpc-core 1.58.0: https://github.com/grpc/grpc-java, Apache 2.0
diff --git a/infra/expr/type/espresso/pom.xml b/infra/expr/type/espresso/pom.xml
index d3681f30bbd..84c9d15da70 100644
--- a/infra/expr/type/espresso/pom.xml
+++ b/infra/expr/type/espresso/pom.xml
@@ -42,12 +42,6 @@
             <artifactId>shardingsphere-infra-util</artifactId>
             <version>${project.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.apache.shardingsphere</groupId>
-            <artifactId>shardingsphere-test-util</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
         
         <dependency>
             <groupId>org.graalvm.polyglot</groupId>
diff --git 
a/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParser.java
 
b/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParser.java
index 44b91ba9018..b95837b97b7 100644
--- 
a/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParser.java
+++ 
b/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParser.java
@@ -19,10 +19,10 @@ package org.apache.shardingsphere.infra.expr.espresso;
 
 import com.google.common.base.Strings;
 import com.google.common.collect.Sets;
+import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
 import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
 import org.apache.shardingsphere.infra.util.groovy.GroovyUtils;
 
-import java.io.File;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -42,12 +42,10 @@ public final class EspressoInlineExpressionParser 
implements InlineExpressionPar
     
     private String inlineExpression;
     
-    private final ReflectContext context = new ReflectContext(JAVA_CLASSPATH);
-    
     static {
-        URL resource = ClassLoader.getSystemResource("build" + File.separator 
+ "libs");
-        String dir = null == resource ? null : resource.getPath();
-        JAVA_CLASSPATH = dir + File.separator + "groovy.jar";
+        URL groovyJarUrl = 
ClassLoader.getSystemResource("build/libs/groovy.jar");
+        ShardingSpherePreconditions.checkNotNull(groovyJarUrl, 
NullPointerException::new);
+        JAVA_CLASSPATH = groovyJarUrl.getPath();
     }
     
     @Override
@@ -72,10 +70,15 @@ public final class EspressoInlineExpressionParser 
implements InlineExpressionPar
     
     @Override
     public List<String> splitAndEvaluate() {
-        return Strings.isNullOrEmpty(inlineExpression) ? 
Collections.emptyList() : 
flatten(evaluate(GroovyUtils.split(handlePlaceHolder(inlineExpression))));
+        try (ReflectContext context = new ReflectContext(JAVA_CLASSPATH)) {
+            if (Strings.isNullOrEmpty(inlineExpression)) {
+                return Collections.emptyList();
+            }
+            return flatten(evaluate(context, 
GroovyUtils.split(handlePlaceHolder(inlineExpression))));
+        }
     }
     
-    private List<ReflectValue> evaluate(final List<String> inlineExpressions) {
+    private List<ReflectValue> evaluate(final ReflectContext context, final 
List<String> inlineExpressions) {
         List<ReflectValue> result = new ArrayList<>(inlineExpressions.size());
         for (String each : inlineExpressions) {
             StringBuilder expression = new 
StringBuilder(handlePlaceHolder(each));
@@ -85,17 +88,17 @@ public final class EspressoInlineExpressionParser 
implements InlineExpressionPar
             if (!each.endsWith("\"")) {
                 expression.append('"');
             }
-            result.add(evaluate(expression.toString()));
+            result.add(evaluate(context, expression.toString()));
         }
         return result;
     }
     
-    private ReflectValue evaluate(final String expression) {
+    private ReflectValue evaluate(final ReflectContext context, final String 
expression) {
         return context.getBindings("java")
                 .getMember("groovy.lang.GroovyShell")
                 .newInstance()
-                .invokeMember("parse", expression)
-                .invokeMember("run");
+                
.invokeMember("parse/(Ljava/lang/String;)Lgroovy/lang/Script;", expression)
+                .invokeMember("run/()Ljava/lang/Object;");
     }
     
     /**
@@ -140,9 +143,9 @@ public final class EspressoInlineExpressionParser 
implements InlineExpressionPar
      */
     @SuppressWarnings("unchecked")
     private Set<List<String>> getCartesianValues(final ReflectValue segment) {
-        Object[] temp = segment.invokeMember("getValues").as(Object[].class);
-        List<Set<String>> result = new ArrayList<>(temp.length);
-        for (Object each : temp) {
+        Object[] segmentAsObjectArray = 
segment.invokeMember("getValues/()[Ljava/lang/Object;").as(Object[].class);
+        List<Set<String>> result = new 
ArrayList<>(segmentAsObjectArray.length);
+        for (Object each : segmentAsObjectArray) {
             if (null == each) {
                 continue;
             }
@@ -163,10 +166,10 @@ public final class EspressoInlineExpressionParser 
implements InlineExpressionPar
      * @return {@link java.lang.String}
      */
     private String assemblySegment(final List<String> cartesianValue, final 
ReflectValue segment) {
-        String[] temp = segment.invokeMember("getStrings").as(String[].class);
+        String[] segmentAsStringArray = 
segment.invokeMember("getStrings/()[Ljava/lang/String;").as(String[].class);
         StringBuilder result = new StringBuilder();
-        for (int i = 0; i < temp.length; i++) {
-            result.append(temp[i]);
+        for (int i = 0; i < segmentAsStringArray.length; i++) {
+            result.append(segmentAsStringArray[i]);
             if (i < cartesianValue.size()) {
                 result.append(cartesianValue.get(i));
             }
diff --git 
a/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/ReflectContext.java
 
b/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/ReflectContext.java
index a187382d943..be7209d69c7 100644
--- 
a/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/ReflectContext.java
+++ 
b/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/ReflectContext.java
@@ -23,7 +23,7 @@ import lombok.SneakyThrows;
  * Reflect Context.
  * Avoid using JDK21 bytecode during compilation. Refer to 
`org.graalvm.polyglot.Context`.
  */
-public final class ReflectContext {
+public final class ReflectContext implements AutoCloseable {
     
     private static final String CONTEXT_CLASS_NAME = 
"org.graalvm.polyglot.Context";
     
@@ -48,7 +48,7 @@ public final class ReflectContext {
     public ReflectContext(final String javaClassPath) {
         Object builderInstance = Class.forName(CONTEXT_CLASS_NAME)
                 .getMethod("newBuilder", String[].class)
-                .invoke(null, (Object) new String[]{});
+                .invoke(null, (Object) new String[0]);
         builderInstance = builderInstance.getClass()
                 .getMethod("allowAllAccess", boolean.class)
                 .invoke(builderInstance, true);
@@ -73,4 +73,10 @@ public final class ReflectContext {
                 .invoke(contextInstance, languageId);
         return new ReflectValue(valueInstance);
     }
+    
+    @Override
+    @SneakyThrows
+    public void close() {
+        
Class.forName(CONTEXT_CLASS_NAME).getMethod("close").invoke(contextInstance);
+    }
 }
diff --git 
a/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/ReflectValue.java
 
b/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/ReflectValue.java
index 8f0c20d7b13..aa46ad95d8a 100644
--- 
a/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/ReflectValue.java
+++ 
b/infra/expr/type/espresso/src/main/java/org/apache/shardingsphere/infra/expr/espresso/ReflectValue.java
@@ -19,6 +19,8 @@ package org.apache.shardingsphere.infra.expr.espresso;
 
 import lombok.SneakyThrows;
 
+import java.util.stream.Stream;
+
 /**
  * Reflect Value.
  * Avoid using JDK21 bytecode during compilation. Refer to 
`org.graalvm.polyglot.Value`.
@@ -55,7 +57,7 @@ public class ReflectValue {
     public ReflectValue newInstance(final Object... arguments) {
         Object resultValueInstance = Class.forName(VALUE_CLASS_NAME)
                 .getMethod("newInstance", Object[].class)
-                .invoke(valueInstance, (Object) arguments);
+                .invoke(valueInstance, new 
Object[]{Stream.of(arguments).toArray()});
         return new ReflectValue(resultValueInstance);
     }
     
diff --git 
a/infra/expr/type/espresso/src/test/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParserTest.java
 
b/infra/expr/type/espresso/src/test/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParserTest.java
index 55694206969..16930098d8c 100644
--- 
a/infra/expr/type/espresso/src/test/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParserTest.java
+++ 
b/infra/expr/type/espresso/src/test/java/org/apache/shardingsphere/infra/expr/espresso/EspressoInlineExpressionParserTest.java
@@ -19,15 +19,14 @@ package org.apache.shardingsphere.infra.expr.espresso;
 
 import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
-import org.apache.shardingsphere.test.util.PropertiesBuilder;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.EnabledForJreRange;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
 import org.junit.jupiter.api.condition.EnabledOnOs;
 import org.junit.jupiter.api.condition.JRE;
 import org.junit.jupiter.api.condition.OS;
 
 import java.util.Collections;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Properties;
 
@@ -38,6 +37,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 
 @EnabledForJreRange(min = JRE.JAVA_21)
 @EnabledOnOs(value = OS.LINUX, disabledReason = "Refer to 
https://www.graalvm.org/jdk21/reference-manual/java-on-truffle/faq/#does-java-running-on-truffle-run-on-hotspot-too
 .")
+@EnabledIfSystemProperty(named = "java.vm.vendor", matches = "GraalVM",
+        disabledReason = "Executing unit tests of this type in batches will 
result in a timeout, while executing unit tests individually works fine.")
 class EspressoInlineExpressionParserTest {
     
     @Test
@@ -49,64 +50,56 @@ class EspressoInlineExpressionParserTest {
     
     @Test
     void assertEvaluateForSimpleString() {
-        List<String> expected = 
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO", 
PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, " 
t_order_0, t_order_1 "))).splitAndEvaluate();
+        List<String> expected = createInlineExpressionParser(" t_order_0, 
t_order_1 ").splitAndEvaluate();
         assertThat(expected.size(), is(2));
         assertThat(expected, hasItems("t_order_0", "t_order_1"));
     }
     
     @Test
     void assertEvaluateForNull() {
-        List<String> expected = 
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO", 
PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"t_order_${null}"))).splitAndEvaluate();
+        List<String> expected = 
createInlineExpressionParser("t_order_${null}").splitAndEvaluate();
         assertThat(expected.size(), is(1));
         assertThat(expected, hasItems("t_order_"));
     }
     
     @Test
     void assertEvaluateForLiteral() {
-        List<String> expected = 
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO", 
PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"t_order_${'xx'}"))).splitAndEvaluate();
+        List<String> expected = 
createInlineExpressionParser("t_order_${'xx'}").splitAndEvaluate();
         assertThat(expected.size(), is(1));
         assertThat(expected, hasItems("t_order_xx"));
     }
     
     @Test
     void assertEvaluateForArray() {
-        List<String> expected = 
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO", 
PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"t_order_${[0, 1, 2]},t_order_item_${[0, 2]}"))).splitAndEvaluate();
+        List<String> expected = createInlineExpressionParser("t_order_${[0, 1, 
2]},t_order_item_${[0, 2]}").splitAndEvaluate();
         assertThat(expected.size(), is(5));
         assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2", 
"t_order_item_0", "t_order_item_2"));
     }
     
     @Test
     void assertEvaluateForRange() {
-        List<String> expected = 
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO", 
PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"t_order_${0..2},t_order_item_${0..1}"))).splitAndEvaluate();
+        List<String> expected = 
createInlineExpressionParser("t_order_${0..2},t_order_item_${0..1}").splitAndEvaluate();
         assertThat(expected.size(), is(5));
         assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2", 
"t_order_item_0", "t_order_item_1"));
     }
     
     @Test
     void assertEvaluateForComplex() {
-        List<String> expected = 
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO", 
PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"t_${['new','old']}_order_${1..2}, t_config"))).splitAndEvaluate();
+        List<String> expected = 
createInlineExpressionParser("t_${['new','old']}_order_${1..2}, 
t_config").splitAndEvaluate();
         assertThat(expected.size(), is(5));
         assertThat(expected, hasItems("t_new_order_1", "t_new_order_2", 
"t_old_order_1", "t_old_order_2", "t_config"));
     }
     
     @Test
     void assertEvaluateForCalculate() {
-        List<String> expected = 
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO", 
PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"t_${[\"new${1+2}\",'old']}_order_${1..2}"))).splitAndEvaluate();
+        List<String> expected = 
createInlineExpressionParser("t_${[\"new${1+2}\",'old']}_order_${1..2}").splitAndEvaluate();
         assertThat(expected.size(), is(4));
         assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2", 
"t_old_order_1", "t_old_order_2"));
     }
     
     @Test
     void assertEvaluateForExpressionPlaceHolder() {
-        List<String> expected = 
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO", 
PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}"))).splitAndEvaluate();
+        List<String> expected = 
createInlineExpressionParser("t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}").splitAndEvaluate();
         assertThat(expected.size(), is(4));
         assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2", 
"t_old_order_1", "t_old_order_2"));
     }
@@ -123,24 +116,26 @@ class EspressoInlineExpressionParserTest {
                 expression.append(",");
             }
         }
-        List<String> expected = 
TypedSPILoader.getService(InlineExpressionParser.class, "ESPRESSO", 
PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
expression.toString()))).splitAndEvaluate();
+        List<String> expected = 
createInlineExpressionParser(expression.toString()).splitAndEvaluate();
         assertThat(expected.size(), is(1024));
         assertThat(expected, hasItems("ds_0.t_user_0", "ds_15.t_user_1023"));
     }
     
     @Test
     void assertHandlePlaceHolder() {
-        assertThat(TypedSPILoader.getService(InlineExpressionParser.class, 
"ESPRESSO", PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"t_$->{[\"new$->{1+2}\"]}"))).handlePlaceHolder(), is("t_${[\"new${1+2}\"]}"));
-        assertThat(TypedSPILoader.getService(InlineExpressionParser.class, 
"ESPRESSO", PropertiesBuilder.build(
-                new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"t_${[\"new$->{1+2}\"]}"))).handlePlaceHolder(), is("t_${[\"new${1+2}\"]}"));
+        String expectdString = "t_${[\"new${1+2}\"]}";
+        
assertThat(createInlineExpressionParser("t_$->{[\"new$->{1+2}\"]}").handlePlaceHolder(),
 is(expectdString));
+        
assertThat(createInlineExpressionParser("t_${[\"new$->{1+2}\"]}").handlePlaceHolder(),
 is(expectdString));
     }
     
     @Test
     void assertEvaluateWithArgs() {
-        assertThrows(UnsupportedOperationException.class, () -> 
TypedSPILoader.getService(
-                InlineExpressionParser.class, "ESPRESSO",
-                PropertiesBuilder.build(new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"${1+2}"))).evaluateWithArgs(new LinkedHashMap<>()));
+        assertThrows(UnsupportedOperationException.class, () -> 
createInlineExpressionParser("${1+2}").evaluateWithArgs(Collections.emptyMap()));
+    }
+    
+    private InlineExpressionParser createInlineExpressionParser(final String 
expression) {
+        Properties props = new Properties();
+        props.put(InlineExpressionParser.INLINE_EXPRESSION_KEY, expression);
+        return TypedSPILoader.getService(InlineExpressionParser.class, 
"ESPRESSO", props);
     }
 }
diff --git a/pom.xml b/pom.xml
index 7ce3705bfdb..228aa37cfa2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -83,7 +83,7 @@
         <json-smart.version>2.4.10</json-smart.version>
         <accessors-smart.version>2.4.9</accessors-smart.version>
         <asm.version>9.3</asm.version>
-        <groovy.version>4.0.10</groovy.version>
+        <groovy.version>4.0.19</groovy.version>
         <freemarker.version>2.3.31</freemarker.version>
         <bytebuddy.version>1.14.8</bytebuddy.version>
         

Reply via email to