Skip to content

Commit

Permalink
[js] use proxy for global bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
lburgazzoli committed Jul 15, 2020
1 parent 7c7702f commit 0614e0d
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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";
Expand All @@ -44,35 +46,46 @@ public List<String> 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);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<IntegrationConfiguration>()

val result = host.eval(
InputStreamReader(inputStream).readText().toScriptSource(),
reader.readText().toScriptSource(),
config,
ScriptEvaluationConfiguration {
//
Expand Down
12 changes: 12 additions & 0 deletions camel-k-runtime-core/src/main/java/org/apache/camel/k/Source.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -28,4 +32,12 @@ public interface Source {
Optional<String> getLoader();
List<String> 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,12 +26,12 @@ public final class RouteBuilders {
private RouteBuilders() {
}

public static EndpointRouteBuilder endpoint(Source source, BiConsumer<InputStream, EndpointRouteBuilder> consumer) {
public static EndpointRouteBuilder endpoint(Source source, BiConsumer<Reader, EndpointRouteBuilder> 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);
}
}
};
Expand Down

0 comments on commit 0614e0d

Please sign in to comment.