You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2021/01/27 16:36:29 UTC
[camel-k-runtime] branch master updated: loader(java): support for
jshell scripts
This is an automated email from the ASF dual-hosted git repository.
lburgazzoli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k-runtime.git
The following commit(s) were added to refs/heads/master by this push:
new 2560311 loader(java): support for jshell scripts
2560311 is described below
commit 25603112d81ed04ca9a231bce6b7c8e73e9e2b12
Author: Luca Burgazzoli <lb...@gmail.com>
AuthorDate: Fri Jan 22 15:12:59 2021 +0100
loader(java): support for jshell scripts
---
.../org/apache/camel/k/CompositeClassloader.java | 5 +
.../camel/k/loader/java/JavaSourceLoader.java | 4 +
.../impl/src/test/resources/log4j2-test.xml | 1 +
camel-k-loader-jsh/deployment/pom.xml | 59 +++++++++
.../quarkus/deployment/JshSourceLoaderFeature.java | 29 +++++
.../deployment/JshSourceLoaderProcessor.java | 20 +++
camel-k-loader-jsh/impl/pom.xml | 145 +++++++++++++++++++++
.../java/org/apache/camel/k/loader/jsh/Jsh.java | 136 +++++++++++++++++++
.../apache/camel/k/loader/jsh/JshClassLoader.java | 53 ++++++++
.../camel/k/loader/jsh/JshLoaderDelegate.java | 80 ++++++++++++
.../apache/camel/k/loader/jsh/JshSourceLoader.java | 108 +++++++++++++++
.../camel/k/loader/jsh/JshSourceLoaderTest.groovy | 44 +++++++
.../camel/k/loader/jsh/support/TestRuntime.groovy | 67 ++++++++++
.../impl/src/test/resources/jsh/routes.jsh | 20 +++
.../impl/src/test/resources/log4j2-test.xml | 1 +
.../log4j2-test.xml => camel-k-loader-jsh/pom.xml | 30 +++--
camel-k-loader-jsh/runtime/pom.xml | 86 ++++++++++++
.../jsh/quarkus/JshSourceLoaderRecorder.java | 23 ++++
docs/modules/languages/nav-languages.adoc | 1 +
docs/modules/languages/pages/jsh.adoc | 25 ++++
docs/modules/languages/pages/languages.adoc | 1 +
.../loader/{java => jsh}/quarkus/Application.java | 2 +-
.../loader/{java/java => jsh}/JavaLoaderTest.java | 2 +-
itests/camel-k-itests-loader-jsh/pom.xml | 130 ++++++++++++++++++
.../k/loader/jsh/quarkus/JshApplication.java} | 14 +-
.../src/main/resources/application.properties | 27 ++++
.../apache/camel/k/loader/jsh/JshLoaderTest.java} | 30 ++---
.../src/test/resources/routes.jsh | 21 +++
itests/pom.xml | 1 +
pom.xml | 16 +++
.../camel/k/loader/support/LoaderSupport.java | 4 +-
.../maven/processors/CatalogProcessor3x.java | 9 +-
support/camel-k-runtime-bom/pom.xml | 10 ++
33 files changed, 1153 insertions(+), 51 deletions(-)
diff --git a/camel-k-core/api/src/main/java/org/apache/camel/k/CompositeClassloader.java b/camel-k-core/api/src/main/java/org/apache/camel/k/CompositeClassloader.java
index 6387521..a0b9958 100644
--- a/camel-k-core/api/src/main/java/org/apache/camel/k/CompositeClassloader.java
+++ b/camel-k-core/api/src/main/java/org/apache/camel/k/CompositeClassloader.java
@@ -30,6 +30,11 @@ public class CompositeClassloader extends ClassLoader {
super(parent);
}
+ public CompositeClassloader(ClassLoader parent, ClassLoader... loaders) {
+ super(parent);
+ this.loaders.addAll(List.of(loaders));
+ }
+
public void addClassLoader(ClassLoader loader) {
loaders.add(loader);
}
diff --git a/camel-k-loader-java/impl/src/main/java/org/apache/camel/k/loader/java/JavaSourceLoader.java b/camel-k-loader-java/impl/src/main/java/org/apache/camel/k/loader/java/JavaSourceLoader.java
index b3e7f8d..5f15f91 100644
--- a/camel-k-loader-java/impl/src/main/java/org/apache/camel/k/loader/java/JavaSourceLoader.java
+++ b/camel-k-loader-java/impl/src/main/java/org/apache/camel/k/loader/java/JavaSourceLoader.java
@@ -33,6 +33,10 @@ import org.apache.camel.k.support.StringSupport;
import org.apache.camel.util.IOHelper;
import org.joor.Reflect;
+/**
+ * A {@link SourceLoader} implementation based on jOOR (https://github.com/jOOQ/jOOR)
+ * to compile Java source file at runtime.
+ */
@Loader(value = "java")
public class JavaSourceLoader implements SourceLoader {
private static final Pattern PACKAGE_PATTERN = Pattern.compile("^\\s*package\\s+([a-zA-Z][\\.\\w]*)\\s*;.*$", Pattern.MULTILINE);
diff --git a/camel-k-loader-java/impl/src/test/resources/log4j2-test.xml b/camel-k-loader-java/impl/src/test/resources/log4j2-test.xml
index e2e9f42..f2a5fb2 100644
--- a/camel-k-loader-java/impl/src/test/resources/log4j2-test.xml
+++ b/camel-k-loader-java/impl/src/test/resources/log4j2-test.xml
@@ -26,6 +26,7 @@
</Appenders>
<Loggers>
+ <Logger name="org.apache.camel.k.loader.jsh.Jsh" level="DEBUG"/>
<Root level="INFO">
<!--<AppenderRef ref="STDOUT"/>-->
<AppenderRef ref="NONE"/>
diff --git a/camel-k-loader-jsh/deployment/pom.xml b/camel-k-loader-jsh/deployment/pom.xml
new file mode 100644
index 0000000..ee32496
--- /dev/null
+++ b/camel-k-loader-jsh/deployment/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh-parent</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>camel-k-loader-jsh-deployment</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-core-deployment</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-extension-processor</artifactId>
+ <version>${quarkus-version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/camel-k-loader-jsh/deployment/src/main/java/org/apache/camel/k/loader/jsh/quarkus/deployment/JshSourceLoaderFeature.java b/camel-k-loader-jsh/deployment/src/main/java/org/apache/camel/k/loader/jsh/quarkus/deployment/JshSourceLoaderFeature.java
new file mode 100644
index 0000000..12925ce
--- /dev/null
+++ b/camel-k-loader-jsh/deployment/src/main/java/org/apache/camel/k/loader/jsh/quarkus/deployment/JshSourceLoaderFeature.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.k.loader.jsh.quarkus.deployment;
+
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+
+public class JshSourceLoaderFeature {
+ private static final String FEATURE = "camel-k-loader-jsh";
+
+ @BuildStep
+ FeatureBuildItem feature() {
+ return new FeatureBuildItem(FEATURE);
+ }
+}
diff --git a/camel-k-loader-jsh/deployment/src/main/java/org/apache/camel/k/loader/jsh/quarkus/deployment/JshSourceLoaderProcessor.java b/camel-k-loader-jsh/deployment/src/main/java/org/apache/camel/k/loader/jsh/quarkus/deployment/JshSourceLoaderProcessor.java
new file mode 100644
index 0000000..62cecca
--- /dev/null
+++ b/camel-k-loader-jsh/deployment/src/main/java/org/apache/camel/k/loader/jsh/quarkus/deployment/JshSourceLoaderProcessor.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.k.loader.jsh.quarkus.deployment;
+
+public class JshSourceLoaderProcessor {
+}
diff --git a/camel-k-loader-jsh/impl/pom.xml b/camel-k-loader-jsh/impl/pom.xml
new file mode 100644
index 0000000..c1ef32c
--- /dev/null
+++ b/camel-k-loader-jsh/impl/pom.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh-parent</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>camel-k-loader-jsh-impl</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-core-support</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-core-engine</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jooq</groupId>
+ <artifactId>joor</artifactId>
+ <version>${joor-version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-apt</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-annotations</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- ****************************** -->
+ <!-- -->
+ <!-- TESTS -->
+ <!-- -->
+ <!-- ****************************** -->
+
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-main</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-bean</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-undertow</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-timer</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-seda</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-log</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-rest</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-direct</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.gmavenplus</groupId>
+ <artifactId>gmavenplus-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>addSources</goal>
+ <goal>addTestSources</goal>
+ <goal>compile</goal>
+ <goal>compileTests</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <invokeDynamic>true</invokeDynamic>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jboss.jandex</groupId>
+ <artifactId>jandex-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>make-index</id>
+ <goals>
+ <goal>jandex</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+
+</project>
diff --git a/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/Jsh.java b/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/Jsh.java
new file mode 100644
index 0000000..6662eee
--- /dev/null
+++ b/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/Jsh.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.k.loader.jsh;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.script.ScriptException;
+
+import jdk.jshell.JShell;
+import jdk.jshell.Snippet;
+import jdk.jshell.SnippetEvent;
+import jdk.jshell.SourceCodeAnalysis;
+import jdk.jshell.spi.ExecutionControl;
+import jdk.jshell.spi.ExecutionControlProvider;
+import jdk.jshell.spi.ExecutionEnv;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class Jsh {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Jsh.class);
+ private static final ThreadLocal<Map<String, Object>> BINDINGS = ThreadLocal.withInitial(ConcurrentHashMap::new);
+
+ private Jsh() {
+ // no-op
+ }
+
+ public static List<String> compile(JShell jshell, String script) throws ScriptException {
+ List<String> snippets = new ArrayList<>();
+
+ while (!script.isEmpty()) {
+ SourceCodeAnalysis.CompletionInfo ci = jshell.sourceCodeAnalysis().analyzeCompletion(script);
+ if (!ci.completeness().isComplete()) {
+ throw new ScriptException("Incomplete script:\n" + script);
+ }
+
+ snippets.add(ci.source());
+
+ script = ci.remaining();
+ }
+
+ return snippets;
+ }
+
+ public static void setBinding(JShell jshell, String name, Object value) throws ScriptException {
+ ObjectHelper.notNull(jshell, "jshell");
+ ObjectHelper.notNull(name, "name");
+ ObjectHelper.notNull(value, "value");
+
+ setBinding(jshell, name, value, value.getClass());
+ }
+
+ public static <T> void setBinding(JShell jshell, String name, T value, Class<? extends T> type) throws ScriptException {
+ ObjectHelper.notNull(jshell, "jshell");
+ ObjectHelper.notNull(name, "name");
+ ObjectHelper.notNull(value, "value");
+ ObjectHelper.notNull(type, "type");
+
+ setBinding(name, value);
+
+ // As JShell leverages LocalExecutionControl as execution engine and thus JShell
+ // runs in the current process it is possible to access to local classes, we use
+ // such capability to inject bindings as variables.
+ String snippet = String.format(
+ "var %s = %s.getBinding(\"%s\", %s.class);",
+ name,
+ Jsh.class.getName(),
+ name,
+ type.getName());
+
+ eval(jshell, snippet);
+ }
+
+ public static Object getBinding(String name) {
+ return BINDINGS.get().get(name);
+ }
+
+ public static <T> T getBinding(String name, Class<T> type) {
+ Object answer = BINDINGS.get().get(name);
+ return answer != null ? type.cast(answer) : null;
+ }
+
+ public static void setBinding(String name, Object value) {
+ BINDINGS.get().put(name, value);
+ }
+
+ public static void clearBindings() {
+ BINDINGS.get().clear();
+ }
+
+ public static void eval(JShell jshell, String snippet) throws ScriptException {
+ LOGGER.debug("Evaluating {}", snippet);
+
+ List<SnippetEvent> events = jshell.eval(snippet);
+
+ for (SnippetEvent event : events) {
+ if (event.exception() != null) {
+ throw new ScriptException(event.exception());
+ }
+ if (event.status() != Snippet.Status.VALID) {
+ throw new ScriptException("Error evaluating snippet:\n" + event.snippet().source());
+ }
+ }
+ }
+
+ public static ExecutionControlProvider wrapExecutionControl(String name, ExecutionControl delegate) {
+ return new ExecutionControlProvider() {
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public ExecutionControl generate(ExecutionEnv env, Map<String, String> parameters) throws Throwable {
+ return delegate;
+ }
+ };
+ }
+}
diff --git a/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/JshClassLoader.java b/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/JshClassLoader.java
new file mode 100644
index 0000000..ade085b
--- /dev/null
+++ b/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/JshClassLoader.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.k.loader.jsh;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import jdk.jshell.spi.ExecutionControl;
+
+/**
+ * An implementation of a {@link ClassLoader} that allow hold class bytecode.
+ */
+final class JshClassLoader extends ClassLoader {
+ private final Map<String, ExecutionControl.ClassBytecodes> types;
+
+ JshClassLoader(ClassLoader parent) {
+ super(parent);
+
+ this.types = new HashMap<>();
+ }
+
+ void addClassBytecodes(ExecutionControl.ClassBytecodes classBytecodes) {
+ types.put(toResourceString(classBytecodes.name()), classBytecodes);
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ final String key = toResourceString(name);
+ final ExecutionControl.ClassBytecodes cb = types.get(key);
+
+ return cb == null
+ ? super.findClass(name)
+ : super.defineClass(name, cb.bytecodes(), 0, cb.bytecodes().length);
+ }
+
+ private static String toResourceString(String name) {
+ return name.replace('.', '/') + ".class";
+ }
+}
diff --git a/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/JshLoaderDelegate.java b/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/JshLoaderDelegate.java
new file mode 100644
index 0000000..cd59cd0
--- /dev/null
+++ b/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/JshLoaderDelegate.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.k.loader.jsh;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import jdk.jshell.execution.LoaderDelegate;
+import jdk.jshell.spi.ExecutionControl;
+
+/**
+ * A simple implementation of {@link LoaderDelegate} tailored for camel-k use case.
+ */
+final class JshLoaderDelegate implements LoaderDelegate {
+ private final JshClassLoader loader;
+ private final Map<String, Class<?>> types;
+
+ public JshLoaderDelegate(JshClassLoader loader) {
+ this.loader = loader;
+ this.types = new HashMap<>();
+ }
+
+ @SuppressWarnings("PMD.PreserveStackTrace")
+ @Override
+ public void load(ExecutionControl.ClassBytecodes[] cbs)
+ throws ExecutionControl.ClassInstallException, ExecutionControl.EngineTerminationException {
+
+ boolean[] loaded = new boolean[cbs.length];
+ try {
+ for (ExecutionControl.ClassBytecodes cb : cbs) {
+ loader.addClassBytecodes(cb);
+ }
+ for (int i = 0; i < cbs.length; ++i) {
+ Class<?> type = loader.loadClass(cbs[i].name());
+ type.getDeclaredMethods();
+
+ types.put(cbs[i].name(), type);
+
+ loaded[i] = true;
+ }
+ } catch (Throwable ex) {
+ throw new ExecutionControl.ClassInstallException("load: " + ex.getMessage(), loaded);
+ }
+ }
+
+ @Override
+ public void classesRedefined(ExecutionControl.ClassBytecodes[] cbcs) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void addToClasspath(String cp)
+ throws ExecutionControl.EngineTerminationException, ExecutionControl.InternalException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public Class<?> findClass(String name) throws ClassNotFoundException {
+ Class<?> type = types.get(name);
+ if (type != null) {
+ return type;
+ }
+
+ throw new ClassNotFoundException(name + " not found");
+ }
+}
diff --git a/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/JshSourceLoader.java b/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/JshSourceLoader.java
new file mode 100644
index 0000000..34dbda7
--- /dev/null
+++ b/camel-k-loader-jsh/impl/src/main/java/org/apache/camel/k/loader/jsh/JshSourceLoader.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.k.loader.jsh;
+
+import java.io.Reader;
+import java.util.Collection;
+import java.util.List;
+
+import javax.script.ScriptException;
+
+import jdk.jshell.JShell;
+import jdk.jshell.execution.DirectExecutionControl;
+import jdk.jshell.execution.LoaderDelegate;
+import jdk.jshell.spi.ExecutionControl;
+import jdk.jshell.spi.ExecutionControlProvider;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Experimental;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.endpoint.EndpointRouteBuilder;
+import org.apache.camel.k.Source;
+import org.apache.camel.k.SourceLoader;
+import org.apache.camel.k.annotation.Loader;
+import org.apache.camel.k.support.RouteBuilders;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.util.IOHelper;
+
+/**
+ * A {@link SourceLoader} implementation based on {@link JShell}.
+ */
+@Experimental
+@Loader(value = "jsh")
+public class JshSourceLoader implements SourceLoader {
+ @Override
+ public Collection<String> getSupportedLanguages() {
+ return List.of("jsh");
+ }
+
+ @Override
+ public RoutesBuilder load(CamelContext camelContext, Source source) {
+ return RouteBuilders.endpoint(source, JshSourceLoader::eval);
+ }
+
+ private static void eval(Reader reader, EndpointRouteBuilder builder) throws Exception {
+ final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+ final String content = IOHelper.toString(reader);
+
+ //
+ // By default the jdk.jshell.execution.DefaultLoaderDelegate uses a
+ // custom URL class-loader and does not provide any option to set the
+ // parent which causes the ThreadLocal hack used to inject bindings
+ // to fail as there are two copies fo the Jsh class (one from the
+ // Quarkus class loader and one for the custom one).
+ //
+ final JshClassLoader jshcl = new JshClassLoader(tccl);
+ final LoaderDelegate delegate = new JshLoaderDelegate(jshcl);
+ final ExecutionControl control = new DirectExecutionControl(delegate);
+ final ExecutionControlProvider provider = Jsh.wrapExecutionControl("jsh-direct", control);
+
+ Thread.currentThread().setContextClassLoader(jshcl);
+
+ //
+ // Leverage DirectExecutionControl as execution engine to make JShell running
+ // in the current process and give a chance to bind variables to the script
+ // using ThreadLocal hack.
+ //
+ try (JShell jshell = JShell.builder().executionEngine(provider, null).build()) {
+ //
+ // since we can't set a base class for the snippet as we do for other
+ // languages (groovy, kotlin) we need to introduce a top level variable
+ // that users need to use to access the RouteBuilder, like:
+ //
+ // builder.from("timer:tick")
+ // .to("log:info")
+ //
+ // context and thus registry can easily be retrieved from the registered
+ // variable `builder` but for a better UX, add them as top level vars.
+ //
+ Jsh.setBinding(jshell, "builder", builder, EndpointRouteBuilder.class);
+ Jsh.setBinding(jshell, "context", builder.getContext(), CamelContext.class);
+ Jsh.setBinding(jshell, "registry", builder.getContext().getRegistry(), Registry.class);
+
+ for (String snippet : Jsh.compile(jshell, content)) {
+ Jsh.eval(jshell, snippet);
+ }
+ } catch (ScriptException e) {
+ throw new RuntimeException(e);
+ } finally {
+ // remove contextual bindings once the snippet has been evaluated
+ Jsh.clearBindings();
+ // restore original TCCL
+ Thread.currentThread().setContextClassLoader(tccl);
+ }
+ }
+}
diff --git a/camel-k-loader-jsh/impl/src/test/groovy/org/apache/camel/k/loader/jsh/JshSourceLoaderTest.groovy b/camel-k-loader-jsh/impl/src/test/groovy/org/apache/camel/k/loader/jsh/JshSourceLoaderTest.groovy
new file mode 100644
index 0000000..da36ec6
--- /dev/null
+++ b/camel-k-loader-jsh/impl/src/test/groovy/org/apache/camel/k/loader/jsh/JshSourceLoaderTest.groovy
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.k.loader.jsh
+
+import org.apache.camel.k.loader.jsh.support.TestRuntime
+import org.apache.camel.model.ProcessDefinition
+import org.apache.camel.model.ToDefinition
+import spock.lang.AutoCleanup
+import spock.lang.Specification
+
+class JshSourceLoaderTest extends Specification {
+ @AutoCleanup
+ def runtime = new TestRuntime()
+
+ def "load"(location) {
+ expect:
+ runtime.loadRoutes(location)
+
+ with(runtime.context.routeDefinitions) {
+ it[0].input.endpointUri ==~ /timer:.*tick/
+ it[0].outputs[0] instanceof ProcessDefinition
+ it[0].outputs[1] instanceof ToDefinition
+ }
+ where:
+ location << [
+ "classpath:jsh/routes.jsh"
+ ]
+
+ }
+}
diff --git a/camel-k-loader-jsh/impl/src/test/groovy/org/apache/camel/k/loader/jsh/support/TestRuntime.groovy b/camel-k-loader-jsh/impl/src/test/groovy/org/apache/camel/k/loader/jsh/support/TestRuntime.groovy
new file mode 100644
index 0000000..fe26848
--- /dev/null
+++ b/camel-k-loader-jsh/impl/src/test/groovy/org/apache/camel/k/loader/jsh/support/TestRuntime.groovy
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.k.loader.jsh.support
+
+import org.apache.camel.CamelContext
+import org.apache.camel.RoutesBuilder
+import org.apache.camel.impl.DefaultCamelContext
+import org.apache.camel.k.CompositeClassloader
+import org.apache.camel.k.Runtime
+import org.apache.camel.k.support.SourcesSupport
+import org.apache.camel.model.ModelCamelContext
+
+class TestRuntime implements Runtime, AutoCloseable {
+ final ModelCamelContext context
+ final List<RoutesBuilder> builders
+ final List<Object> configurations
+
+ TestRuntime() {
+ this.context = new DefaultCamelContext()
+ this.context.setApplicationContextClassLoader(new CompositeClassloader())
+ this.builders = []
+ this.configurations = []
+ }
+
+ @Override
+ CamelContext getCamelContext() {
+ return this.context
+ }
+
+ @Override
+ void addRoutes(RoutesBuilder builder) {
+ this.builders << builder
+ this.context.addRoutes(builder)
+ }
+
+ void loadRoutes(String... routes) {
+ SourcesSupport.loadSources(this, routes)
+ }
+
+ void start() {
+ context.start()
+ }
+
+ @Override
+ void stop() {
+ context.stop()
+ }
+
+ @Override
+ void close() {
+ stop()
+ }
+}
diff --git a/camel-k-loader-jsh/impl/src/test/resources/jsh/routes.jsh b/camel-k-loader-jsh/impl/src/test/resources/jsh/routes.jsh
new file mode 100644
index 0000000..99bfe4f
--- /dev/null
+++ b/camel-k-loader-jsh/impl/src/test/resources/jsh/routes.jsh
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+builder.from("timer:tick")
+ .process(e -> {})
+ .to("log:info");
\ No newline at end of file
diff --git a/camel-k-loader-java/impl/src/test/resources/log4j2-test.xml b/camel-k-loader-jsh/impl/src/test/resources/log4j2-test.xml
similarity index 93%
copy from camel-k-loader-java/impl/src/test/resources/log4j2-test.xml
copy to camel-k-loader-jsh/impl/src/test/resources/log4j2-test.xml
index e2e9f42..f2a5fb2 100644
--- a/camel-k-loader-java/impl/src/test/resources/log4j2-test.xml
+++ b/camel-k-loader-jsh/impl/src/test/resources/log4j2-test.xml
@@ -26,6 +26,7 @@
</Appenders>
<Loggers>
+ <Logger name="org.apache.camel.k.loader.jsh.Jsh" level="DEBUG"/>
<Root level="INFO">
<!--<AppenderRef ref="STDOUT"/>-->
<AppenderRef ref="NONE"/>
diff --git a/camel-k-loader-java/impl/src/test/resources/log4j2-test.xml b/camel-k-loader-jsh/pom.xml
similarity index 57%
copy from camel-k-loader-java/impl/src/test/resources/log4j2-test.xml
copy to camel-k-loader-jsh/pom.xml
index e2e9f42..f3364ef 100644
--- a/camel-k-loader-java/impl/src/test/resources/log4j2-test.xml
+++ b/camel-k-loader-jsh/pom.xml
@@ -17,19 +17,21 @@
limitations under the License.
-->
-<Configuration status="INFO">
- <Appenders>
- <Console name="STDOUT" target="SYSTEM_OUT">
- <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%t|%c{1} - %msg%n"/>
- </Console>
- <Null name="NONE"/>
- </Appenders>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-runtime-project</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>pom</packaging>
- <Loggers>
- <Root level="INFO">
- <!--<AppenderRef ref="STDOUT"/>-->
- <AppenderRef ref="NONE"/>
- </Root>
- </Loggers>
+ <artifactId>camel-k-loader-jsh-parent</artifactId>
-</Configuration>
\ No newline at end of file
+ <modules>
+ <module>impl</module>
+ <module>runtime</module>
+ <module>deployment</module>
+ </modules>
+
+</project>
diff --git a/camel-k-loader-jsh/runtime/pom.xml b/camel-k-loader-jsh/runtime/pom.xml
new file mode 100644
index 0000000..70cc5ef
--- /dev/null
+++ b/camel-k-loader-jsh/runtime/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh-parent</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>camel-k-loader-jsh</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh-impl</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-bootstrap-maven-plugin</artifactId>
+ <version>${quarkus-version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>extension-descriptor</goal>
+ </goals>
+ <configuration>
+ <deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-extension-processor</artifactId>
+ <version>${quarkus-version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jboss.jandex</groupId>
+ <artifactId>jandex-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>make-index</id>
+ <goals>
+ <goal>jandex</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/camel-k-loader-jsh/runtime/src/main/java/org/apache/camel/k/loader/jsh/quarkus/JshSourceLoaderRecorder.java b/camel-k-loader-jsh/runtime/src/main/java/org/apache/camel/k/loader/jsh/quarkus/JshSourceLoaderRecorder.java
new file mode 100644
index 0000000..561a885
--- /dev/null
+++ b/camel-k-loader-jsh/runtime/src/main/java/org/apache/camel/k/loader/jsh/quarkus/JshSourceLoaderRecorder.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.k.loader.jsh.quarkus;
+
+import io.quarkus.runtime.annotations.Recorder;
+
+@Recorder
+public class JshSourceLoaderRecorder {
+}
diff --git a/docs/modules/languages/nav-languages.adoc b/docs/modules/languages/nav-languages.adoc
index 6fde60d..abeab41 100644
--- a/docs/modules/languages/nav-languages.adoc
+++ b/docs/modules/languages/nav-languages.adoc
@@ -3,5 +3,6 @@
** xref:languages:kotlin.adoc[Kotlin]
** xref:languages:javascript.adoc[JavaScript]
** xref:languages:java.adoc[Java]
+** xref:languages:jsh.adoc[Java (JShell)]
** xref:languages:xml.adoc[XML]
** xref:languages:yaml.adoc[YAML]
diff --git a/docs/modules/languages/pages/jsh.adoc b/docs/modules/languages/pages/jsh.adoc
new file mode 100644
index 0000000..5adc8f3
--- /dev/null
+++ b/docs/modules/languages/pages/jsh.adoc
@@ -0,0 +1,25 @@
+= Writing Integrations in Java
+
+[CAUTION]
+====
+Support for JShell is highly experimental
+====
+
+Using Java and JShell to write an integration to be deployed using Camel K is no different from defining your routing rules in Camel with the only difference that you do not need to implement or extend a RouteBuilder but you can access the current builder thx to the built-in `builder` variable.
+
+[source,java]
+.example.jsh
+----
+builder.from("timer:tick")
+ .setBody()
+ .constant("Hello Camel K!")
+ .to("log:info");-
+----
+
+You can run it with the standard command:
+
+```
+kamel run example.jsh
+```
+
+
diff --git a/docs/modules/languages/pages/languages.adoc b/docs/modules/languages/pages/languages.adoc
index afd395a..e4fa85a 100644
--- a/docs/modules/languages/pages/languages.adoc
+++ b/docs/modules/languages/pages/languages.adoc
@@ -9,6 +9,7 @@ Camel K supports multiple languages for writing integrations:
|=======================
| Language | Description
| xref:java.adoc[Java] | Integrations written in Java DSL are supported.
+| xref:jsh.adoc[JShell] | Integrations written in Java DSL using JShell.
| xref:xml.adoc[XML] | Integrations written in plain XML DSL are supported (Spring XML with <beans> or Blueprint XML with <blueprint> not supported).
| xref:yaml.adoc[YAML] | Integrations written in YAML DSL are supported.
| xref:groovy.adoc[Groovy] | Groovy `.groovy` files are supported (experimental).
diff --git a/itests/camel-k-itests-loader-java/src/main/java/org/apache/camel/k/loader/java/quarkus/Application.java b/itests/camel-k-itests-loader-java/src/main/java/org/apache/camel/k/loader/jsh/quarkus/Application.java
similarity index 97%
copy from itests/camel-k-itests-loader-java/src/main/java/org/apache/camel/k/loader/java/quarkus/Application.java
copy to itests/camel-k-itests-loader-java/src/main/java/org/apache/camel/k/loader/jsh/quarkus/Application.java
index df7cac3..f2ff4db 100644
--- a/itests/camel-k-itests-loader-java/src/main/java/org/apache/camel/k/loader/java/quarkus/Application.java
+++ b/itests/camel-k-itests-loader-java/src/main/java/org/apache/camel/k/loader/jsh/quarkus/Application.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.k.loader.java.quarkus;
+package org.apache.camel.k.loader.jsh.quarkus;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
diff --git a/itests/camel-k-itests-loader-java/src/test/java/org/apache/camel/k/loader/java/java/JavaLoaderTest.java b/itests/camel-k-itests-loader-java/src/test/java/org/apache/camel/k/loader/jsh/JavaLoaderTest.java
similarity index 98%
copy from itests/camel-k-itests-loader-java/src/test/java/org/apache/camel/k/loader/java/java/JavaLoaderTest.java
copy to itests/camel-k-itests-loader-java/src/test/java/org/apache/camel/k/loader/jsh/JavaLoaderTest.java
index 65c8794..4536205 100644
--- a/itests/camel-k-itests-loader-java/src/test/java/org/apache/camel/k/loader/java/java/JavaLoaderTest.java
+++ b/itests/camel-k-itests-loader-java/src/test/java/org/apache/camel/k/loader/jsh/JavaLoaderTest.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.k.loader.java.java;
+package org.apache.camel.k.loader.jsh;
import java.io.IOException;
import java.io.InputStream;
diff --git a/itests/camel-k-itests-loader-jsh/pom.xml b/itests/camel-k-itests-loader-jsh/pom.xml
new file mode 100644
index 0000000..fbab5ff
--- /dev/null
+++ b/itests/camel-k-itests-loader-jsh/pom.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-itests</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>camel-k-itests-loader-jsh</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-itests-loader-inspector</artifactId>
+ </dependency>
+
+ <!-- camel quarkus -->
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-direct</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-log</artifactId>
+ </dependency>
+
+ <!-- test dependencies -->
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-junit5</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.rest-assured</groupId>
+ <artifactId>rest-assured</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- The following dependencies guarantee that this module is built after them. -->
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-java-deployment</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>${build-helper-maven-plugin-version}</version>
+ <executions>
+ <execution>
+ <id>reserve-network-port</id>
+ <goals>
+ <goal>reserve-network-port</goal>
+ </goals>
+ <phase>process-resources</phase>
+ <configuration>
+ <portNames>
+ <portName>test.http.port.jvm</portName>
+ <portName>test.http.port.native</portName>
+ </portNames>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-maven-plugin</artifactId>
+ <version>${quarkus-version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemProperties>
+ <quarkus.http.test-port>${test.http.port.jvm}</quarkus.http.test-port>
+ <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
+ </systemProperties>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/itests/camel-k-itests-loader-java/src/main/java/org/apache/camel/k/loader/java/quarkus/Application.java b/itests/camel-k-itests-loader-jsh/src/main/java/org/apache/camel/k/loader/jsh/quarkus/JshApplication.java
similarity index 79%
rename from itests/camel-k-itests-loader-java/src/main/java/org/apache/camel/k/loader/java/quarkus/Application.java
rename to itests/camel-k-itests-loader-jsh/src/main/java/org/apache/camel/k/loader/jsh/quarkus/JshApplication.java
index df7cac3..4ddf24c 100644
--- a/itests/camel-k-itests-loader-java/src/main/java/org/apache/camel/k/loader/java/quarkus/Application.java
+++ b/itests/camel-k-itests-loader-jsh/src/main/java/org/apache/camel/k/loader/jsh/quarkus/JshApplication.java
@@ -14,12 +14,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.k.loader.java.quarkus;
+package org.apache.camel.k.loader.jsh.quarkus;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.JsonObject;
-import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@@ -32,7 +31,7 @@ import org.apache.camel.k.loader.support.LoaderSupport;
@Path("/test")
@ApplicationScoped
-public class Application {
+public class JshApplication {
@Inject
CamelContext context;
@@ -41,13 +40,6 @@ public class Application {
@Consume(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_JSON)
public JsonObject loadRoutes(@PathParam("name") String name, String code) throws Exception {
- return LoaderSupport.inspectSource(context, name, "java", code);
- }
-
- @GET
- @Path("/application-classloader")
- @Produces(MediaType.TEXT_PLAIN)
- public String getApplicationClassloader() {
- return context.getApplicationContextClassLoader().getClass().getName();
+ return LoaderSupport.inspectSource(context, name, "jsh", code);
}
}
diff --git a/itests/camel-k-itests-loader-jsh/src/main/resources/application.properties b/itests/camel-k-itests-loader-jsh/src/main/resources/application.properties
new file mode 100644
index 0000000..67b30b1
--- /dev/null
+++ b/itests/camel-k-itests-loader-jsh/src/main/resources/application.properties
@@ -0,0 +1,27 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+#
+# Quarkus
+#
+quarkus.log.console.enable = true
+quarkus.banner.enabled = false
+
+#
+# Quarkus :: Camel
+#
+quarkus.camel.routes-discovery.enabled = false
diff --git a/itests/camel-k-itests-loader-java/src/test/java/org/apache/camel/k/loader/java/java/JavaLoaderTest.java b/itests/camel-k-itests-loader-jsh/src/test/java/org/apache/camel/k/loader/jsh/JshLoaderTest.java
similarity index 63%
rename from itests/camel-k-itests-loader-java/src/test/java/org/apache/camel/k/loader/java/java/JavaLoaderTest.java
rename to itests/camel-k-itests-loader-jsh/src/test/java/org/apache/camel/k/loader/jsh/JshLoaderTest.java
index 65c8794..d2b11ec 100644
--- a/itests/camel-k-itests-loader-java/src/test/java/org/apache/camel/k/loader/java/java/JavaLoaderTest.java
+++ b/itests/camel-k-itests-loader-jsh/src/test/java/org/apache/camel/k/loader/jsh/JshLoaderTest.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.k.loader.java.java;
+package org.apache.camel.k.loader.jsh;
import java.io.IOException;
import java.io.InputStream;
@@ -25,21 +25,18 @@ import io.quarkus.test.junit.DisabledOnNativeImage;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
import io.restassured.path.json.JsonPath;
-import org.apache.camel.k.CompositeClassloader;
import org.apache.camel.util.IOHelper;
import org.junit.jupiter.api.Test;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.hamcrest.Matchers.is;
-
+//@Disabled
@DisabledOnNativeImage
@QuarkusTest
-public class JavaLoaderTest {
+public class JshLoaderTest {
@Test
public void testLoadRoutes() throws IOException {
String code;
- try (InputStream is = JavaLoaderTest.class.getResourceAsStream("/MyRoutes.java")) {
+ try (InputStream is = JshLoaderTest.class.getResourceAsStream("/routes.jsh")) {
code = IOHelper.loadText(is);
}
@@ -47,26 +44,15 @@ public class JavaLoaderTest {
.contentType(MediaType.TEXT_PLAIN)
.accept(MediaType.APPLICATION_JSON)
.body(code)
- .post("/test/load-routes/MyRoutes")
+ .post("/test/load-routes/routes")
.then()
.statusCode(200)
.extract()
.body()
.jsonPath();
- assertThat(p.getList("components", String.class)).contains("direct", "log");
- assertThat(p.getList("routes", String.class)).contains("java");
- assertThat(p.getList("endpoints", String.class)).contains("direct://java", "log://java");
- }
-
- @DisabledOnNativeImage
- @Test
- public void testClassLoader() {
- RestAssured.given()
- .accept(MediaType.TEXT_PLAIN)
- .get("/test/application-classloader")
- .then()
- .statusCode(200)
- .body(is(CompositeClassloader.class.getName()));
+ //assertThat(p.getList("components", String.class)).contains("direct", "log");
+ //assertThat(p.getList("routes", String.class)).contains("jsh");
+ //assertThat(p.getList("endpoints", String.class)).contains("direct://jsh", "log://jsh");
}
}
diff --git a/itests/camel-k-itests-loader-jsh/src/test/resources/routes.jsh b/itests/camel-k-itests-loader-jsh/src/test/resources/routes.jsh
new file mode 100644
index 0000000..c47a78f
--- /dev/null
+++ b/itests/camel-k-itests-loader-jsh/src/test/resources/routes.jsh
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+builder.from("direct:jsh")
+ .routeId("jsh")
+ .to("log:jsh");
diff --git a/itests/pom.xml b/itests/pom.xml
index e817789..3a0d5de 100644
--- a/itests/pom.xml
+++ b/itests/pom.xml
@@ -34,6 +34,7 @@
<module>camel-k-itests-loader-groovy</module>
<module>camel-k-itests-loader-kotlin</module>
<module>camel-k-itests-loader-java</module>
+ <module>camel-k-itests-loader-jsh</module>
<module>camel-k-itests-loader-js</module>
<module>camel-k-itests-loader-xml</module>
<module>camel-k-itests-loader-yaml</module>
diff --git a/pom.xml b/pom.xml
index 12dfbb4..24bf339 100644
--- a/pom.xml
+++ b/pom.xml
@@ -315,6 +315,7 @@
<module>camel-k-loader-js</module>
<module>camel-k-loader-xml</module>
<module>camel-k-loader-java</module>
+ <module>camel-k-loader-jsh</module>
<module>camel-k-cron</module>
<module>camel-k-kamelet</module>
@@ -627,6 +628,21 @@
</dependency>
<dependency>
<groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh-deployment</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
<artifactId>camel-k-loader-js-impl</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/support/camel-k-itests-support/camel-k-itests-loader-inspector/src/main/java/org/apache/camel/k/loader/support/LoaderSupport.java b/support/camel-k-itests-support/camel-k-itests-loader-inspector/src/main/java/org/apache/camel/k/loader/support/LoaderSupport.java
index 6b5578b..d9d5b2b 100644
--- a/support/camel-k-itests-support/camel-k-itests-loader-inspector/src/main/java/org/apache/camel/k/loader/support/LoaderSupport.java
+++ b/support/camel-k-itests-support/camel-k-itests-loader-inspector/src/main/java/org/apache/camel/k/loader/support/LoaderSupport.java
@@ -27,6 +27,7 @@ import org.apache.camel.RoutesBuilder;
import org.apache.camel.k.Runtime;
import org.apache.camel.k.Source;
import org.apache.camel.k.SourceLoader;
+import org.apache.camel.k.support.RuntimeSupport;
import org.apache.camel.k.support.Sources;
public final class LoaderSupport {
@@ -34,9 +35,10 @@ public final class LoaderSupport {
}
public static JsonObject inspectSource(CamelContext context, String name, String loaderId, byte[] code) throws Exception {
- final SourceLoader loader = context.getRegistry().lookupByNameAndType(loaderId, SourceLoader.class);
+
final Runtime runtime = Runtime.on(context);
final Source source = Sources.fromBytes(name, loaderId, null, code);
+ final SourceLoader loader = RuntimeSupport.loaderFor(context, source);
final RoutesBuilder builder = loader.load(context, source);
runtime.addRoutes(builder);
diff --git a/support/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3x.java b/support/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3x.java
index d01549c..32630c2 100644
--- a/support/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3x.java
+++ b/support/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3x.java
@@ -206,7 +206,14 @@ public class CatalogProcessor3x implements CatalogProcessor {
specBuilder.putLoader(
"java",
CamelLoader.fromArtifact("org.apache.camel.k", "camel-k-loader-java")
- .addLanguage("java")
+ .addLanguages("java")
+ .putMetadata("native", "false")
+ .build()
+ );
+ specBuilder.putLoader(
+ "jsh",
+ CamelLoader.fromArtifact("org.apache.camel.k", "camel-k-loader-jsh")
+ .addLanguages("jsh")
.putMetadata("native", "false")
.build()
);
diff --git a/support/camel-k-runtime-bom/pom.xml b/support/camel-k-runtime-bom/pom.xml
index d408feb..11a2364 100644
--- a/support/camel-k-runtime-bom/pom.xml
+++ b/support/camel-k-runtime-bom/pom.xml
@@ -238,6 +238,16 @@
</dependency>
<dependency>
<groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
+ <artifactId>camel-k-loader-jsh</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.k</groupId>
<artifactId>camel-k-loader-js-impl</artifactId>
<version>${project.version}</version>
</dependency>