1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.shardingsphere.infra.expr.espresso;
19
20 import lombok.SneakyThrows;
21
22 /**
23 * Reflect Context.
24 * Avoid using JDK21 bytecode during compilation. Refer to `org.graalvm.polyglot.Context`.
25 */
26 public final class ReflectContext implements AutoCloseable {
27
28 private static final String CONTEXT_CLASS_NAME = "org.graalvm.polyglot.Context";
29
30 private final Object contextInstance;
31
32 /**
33 * This method is a simulation of the following operation.
34 * <pre class="code">
35 * private final Context context = Context.newBuilder("java")
36 * .allowAllAccess(true)
37 * .allowValueSharing(false)
38 * .option("java.Classpath", JAVA_CLASSPATH)
39 * .build();
40 * </pre>
41 * TODO <a href="https://github.com/oracle/graal/issues/4555">oracle/graal#4555</a> not yet closed.
42 * Maybe sometimes shardingsphere need `.option("java.Properties.org.graalvm.home", System.getenv("JAVA_HOME")).
43 *
44 * @param javaClassPath java class path
45 */
46 @SneakyThrows
47 public ReflectContext(final String javaClassPath) {
48 Object builderInstance = Class.forName(CONTEXT_CLASS_NAME)
49 .getMethod("newBuilder", String[].class)
50 .invoke(null, (Object) new String[]{"java"});
51 builderInstance = builderInstance.getClass()
52 .getMethod("allowAllAccess", boolean.class)
53 .invoke(builderInstance, true);
54 builderInstance = builderInstance.getClass()
55 .getMethod("allowValueSharing", boolean.class)
56 .invoke(builderInstance, false);
57 builderInstance = builderInstance.getClass()
58 .getMethod("option", String.class, String.class)
59 .invoke(builderInstance, "java.Classpath", javaClassPath);
60 contextInstance = builderInstance.getClass()
61 .getMethod("build")
62 .invoke(builderInstance);
63 }
64
65 /**
66 * Returns a value that represents the top-most bindings of a language.
67 *
68 * @param languageId languageId
69 * @return {@link org.apache.shardingsphere.infra.expr.espresso.ReflectValue}
70 */
71 @SneakyThrows
72 public ReflectValue getBindings(final String languageId) {
73 Object valueInstance = Class.forName(CONTEXT_CLASS_NAME)
74 .getMethod("getBindings", String.class)
75 .invoke(contextInstance, languageId);
76 return new ReflectValue(valueInstance);
77 }
78
79 @Override
80 @SneakyThrows
81 public void close() {
82 Class.forName(CONTEXT_CLASS_NAME).getMethod("close").invoke(contextInstance);
83 }
84 }