From 0614e0d01dd3a28f13256a087b67d2ad65f75a70 Mon Sep 17 00:00:00 2001 From: lburgazzoli Date: Wed, 15 Jul 2020 19:30:56 +0200 Subject: [PATCH] [js] use proxy for global bindings --- .../k/loader/js/JavaScriptSourceLoader.java | 65 +++++++++++-------- .../k/loader/kotlin/KotlinSourceLoader.kt | 7 +- .../main/java/org/apache/camel/k/Source.java | 12 ++++ .../apache/camel/k/support/RouteBuilders.java | 8 +-- 4 files changed, 59 insertions(+), 33 deletions(-) diff --git a/camel-k-loader-js/src/main/java/org/apache/camel/k/loader/js/JavaScriptSourceLoader.java b/camel-k-loader-js/src/main/java/org/apache/camel/k/loader/js/JavaScriptSourceLoader.java index f32ea0e9d..d8de8e4e4 100644 --- a/camel-k-loader-js/src/main/java/org/apache/camel/k/loader/js/JavaScriptSourceLoader.java +++ b/camel-k-loader-js/src/main/java/org/apache/camel/k/loader/js/JavaScriptSourceLoader.java @@ -16,8 +16,7 @@ */ package org.apache.camel.k.loader.js; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; +import java.io.Reader; import java.util.Collections; import java.util.List; @@ -29,10 +28,13 @@ import org.apache.camel.k.SourceLoader; import org.apache.camel.k.annotation.Loader; import org.apache.camel.k.loader.js.dsl.IntegrationConfiguration; +import org.apache.camel.k.support.RouteBuilders; import org.apache.camel.support.LifecycleStrategySupport; import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Value; +import static org.graalvm.polyglot.Source.newBuilder; + @Loader("js") public class JavaScriptSourceLoader implements SourceLoader { private static final String LANGUAGE_ID = "js"; @@ -44,35 +46,46 @@ public List getSupportedLanguages() { @Override public Result load(Runtime runtime, Source source) throws Exception { - RoutesBuilder builder = new EndpointRouteBuilder() { - @Override - public void configure() throws Exception { - final Context context = Context.newBuilder("js").allowAllAccess(true).build(); + RoutesBuilder builder = RouteBuilders.endpoint(source, JavaScriptSourceLoader::doLoad); + + return SourceLoader.Result.on(builder); + } - try (InputStream is = source.resolveAsInputStream(getContext())) { - Value bindings = context.getBindings(LANGUAGE_ID); + private static void doLoad(Reader reader, EndpointRouteBuilder builder) { + final Context context = Context.newBuilder("js").allowAllAccess(true).build(); + final Value bindings = context.getBindings(LANGUAGE_ID); - // configure bindings - bindings.putMember("__dsl", new IntegrationConfiguration(this)); + // configure bindings + bindings.putMember("__dsl", new IntegrationConfiguration(builder)); - final String script = new String(is.readAllBytes(), StandardCharsets.UTF_8); - final String wrappedScript = "with (__dsl) { " + script + " }"; + // + // Expose IntegrationConfiguration methods to global scope. + // + context.eval(LANGUAGE_ID, "" + + "Object.setPrototypeOf(globalThis, new Proxy(Object.prototype, {" + + " has(target, key) {" + + " return key in __dsl || key in target;" + + " }," + + " get(target, key, receiver) {" + + " return Reflect.get((key in __dsl) ? __dsl : target, key, receiver);" + + " }" + + "}));"); - context.eval(LANGUAGE_ID, wrappedScript); + // + // Run the script. + // + context.eval( + newBuilder(LANGUAGE_ID, reader, "Unnamed").buildLiteral() + ); - // - // Close the polyglot context when the camel context stops - // - getContext().addLifecycleStrategy(new LifecycleStrategySupport() { - @Override - public void onContextStop(CamelContext camelContext) { - context.close(true); - } - }); - } + // + // Close the polyglot context when the camel context stops + // + builder.getContext().addLifecycleStrategy(new LifecycleStrategySupport() { + @Override + public void onContextStop(CamelContext camelContext) { + context.close(true); } - }; - - return Result.on(builder); + }); } } diff --git a/camel-k-loader-kotlin/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/KotlinSourceLoader.kt b/camel-k-loader-kotlin/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/KotlinSourceLoader.kt index 98f334c13..908bb9817 100644 --- a/camel-k-loader-kotlin/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/KotlinSourceLoader.kt +++ b/camel-k-loader-kotlin/camel-k-loader-kotlin/src/main/kotlin/org/apache/camel/k/loader/kotlin/KotlinSourceLoader.kt @@ -27,6 +27,7 @@ import org.apache.camel.k.support.RouteBuilders import org.slf4j.LoggerFactory import java.io.InputStream import java.io.InputStreamReader +import java.io.Reader import kotlin.script.experimental.api.ResultValue import kotlin.script.experimental.api.ScriptDiagnostic import kotlin.script.experimental.api.ScriptEvaluationConfiguration @@ -45,18 +46,18 @@ class KotlinSourceLoader : SourceLoader { @Throws(Exception::class) override fun load(runtime: Runtime, source: Source): SourceLoader.Result { val builder = RouteBuilders.endpoint(source) { - inputStream, builder -> doLoad(inputStream, builder) + reader, builder -> doLoad(reader, builder) } return SourceLoader.Result.on(builder) } - private fun doLoad(inputStream: InputStream, builder: EndpointRouteBuilder) { + private fun doLoad(reader: Reader, builder: EndpointRouteBuilder) { val host = BasicJvmScriptingHost() val config = createJvmCompilationConfigurationFromTemplate() val result = host.eval( - InputStreamReader(inputStream).readText().toScriptSource(), + reader.readText().toScriptSource(), config, ScriptEvaluationConfiguration { // diff --git a/camel-k-runtime-core/src/main/java/org/apache/camel/k/Source.java b/camel-k-runtime-core/src/main/java/org/apache/camel/k/Source.java index 0e8c1c283..a14a17d6d 100644 --- a/camel-k-runtime-core/src/main/java/org/apache/camel/k/Source.java +++ b/camel-k-runtime-core/src/main/java/org/apache/camel/k/Source.java @@ -17,6 +17,10 @@ package org.apache.camel.k; import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Optional; @@ -28,4 +32,12 @@ public interface Source { Optional getLoader(); List getInterceptors(); InputStream resolveAsInputStream(CamelContext ctx); + + default Reader resolveAsReader(CamelContext ctx) { + return resolveAsReader(ctx, StandardCharsets.UTF_8); + } + + default Reader resolveAsReader(CamelContext ctx, Charset charset) { + return new InputStreamReader(resolveAsInputStream(ctx), charset); + } } diff --git a/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/RouteBuilders.java b/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/RouteBuilders.java index 261eb99db..94d1c899e 100644 --- a/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/RouteBuilders.java +++ b/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/RouteBuilders.java @@ -16,7 +16,7 @@ */ package org.apache.camel.k.support; -import java.io.InputStream; +import java.io.Reader; import java.util.function.BiConsumer; import org.apache.camel.builder.endpoint.EndpointRouteBuilder; @@ -26,12 +26,12 @@ public final class RouteBuilders { private RouteBuilders() { } - public static EndpointRouteBuilder endpoint(Source source, BiConsumer consumer) { + public static EndpointRouteBuilder endpoint(Source source, BiConsumer consumer) { return new EndpointRouteBuilder() { @Override public void configure() throws Exception { - try (InputStream is = source.resolveAsInputStream(getContext())) { - consumer.accept(is, this); + try (Reader reader = source.resolveAsReader(getContext())) { + consumer.accept(reader, this); } } };