This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
commit f417456dd0981c96dafe83976f73eadb506a89e9 Author: Claus Ibsen <[email protected]> AuthorDate: Sat Dec 25 16:03:30 2021 +0100 CAMEL-17382: camel-jsh-dsl - JavaShell DSL support --- dsl/camel-jsh-dsl/pom.xml | 145 +++++++++++++++++++++ .../services/org/apache/camel/routes-loader/jsh | 2 + dsl/camel-jsh-dsl/src/main/docs/jsh-dsl.adoc | 12 ++ .../main/java/org/apache/camel/dsl/jsh/Jsh.java | 135 +++++++++++++++++++ .../org/apache/camel/dsl/jsh/JshClassLoader.java | 52 ++++++++ .../apache/camel/dsl/jsh/JshLoaderDelegate.java | 80 ++++++++++++ .../camel/dsl/jsh/JshRoutesBuilderLoader.java | 112 ++++++++++++++++ .../apache/camel/dsl/jsh/JshSourceLoaderTest.java | 60 +++++++++ .../src/test/resources/log4j2-test.properties | 31 +++++ .../src/test/resources/routes/MyRoute.jsh | 20 +++ dsl/pom.xml | 1 + parent/pom.xml | 5 + 12 files changed, 655 insertions(+) diff --git a/dsl/camel-jsh-dsl/pom.xml b/dsl/camel-jsh-dsl/pom.xml new file mode 100644 index 0000000..861ddda --- /dev/null +++ b/dsl/camel-jsh-dsl/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/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>dsl</artifactId> + <version>3.15.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-jsh-dsl</artifactId> + <packaging>jar</packaging> + <name>Camel :: JavaShell DSL</name> + <description>Camel DSL with JavaShell</description> + + <properties> + <firstVersion>3.15.0</firstVersion> + <supportLevel>Experimental</supportLevel> + <sourcecheckExcludes> + **/resources/**/My*.java + </sourcecheckExcludes> + <sourcecheckExcludesComma> + ${sourcecheckExcludes}, + </sourcecheckExcludesComma> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-endpointdsl-support</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-main</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-direct</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-mock</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core-languages</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-log</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-telegram</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-seda</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test-junit5</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-jcl</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + + <build> + <plugins> + <plugin> + <groupId>org.apache.camel</groupId> + <artifactId>camel-package-maven-plugin</artifactId> + <executions> + <execution> + <id>generate-spi</id> + <goals> + <goal>generate-spi</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file diff --git a/dsl/camel-jsh-dsl/src/generated/resources/META-INF/services/org/apache/camel/routes-loader/jsh b/dsl/camel-jsh-dsl/src/generated/resources/META-INF/services/org/apache/camel/routes-loader/jsh new file mode 100644 index 0000000..f8cf758 --- /dev/null +++ b/dsl/camel-jsh-dsl/src/generated/resources/META-INF/services/org/apache/camel/routes-loader/jsh @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.dsl.jsh.JshRoutesBuilderLoader diff --git a/dsl/camel-jsh-dsl/src/main/docs/jsh-dsl.adoc b/dsl/camel-jsh-dsl/src/main/docs/jsh-dsl.adoc new file mode 100644 index 0000000..d71a63b --- /dev/null +++ b/dsl/camel-jsh-dsl/src/main/docs/jsh-dsl.adoc @@ -0,0 +1,12 @@ += JavaShell DSL Component +//TODO there is no .json file for this doc page, so it is not updated automatically by UpdateReadmeMojo. +//Header attributes written by hand. +:doctitle: JavaShell DSL +:artifactid: camel-jsh-dsl +:description: Camel DSL with JavaShell +:supportlevel: Experimental/Preview +:since: 3.15 +//Manually maintained attributes +:group: DSL + +See xref:manual:ROOT:dsl.adoc[DSL] diff --git a/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/Jsh.java b/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/Jsh.java new file mode 100644 index 0000000..8b29d71 --- /dev/null +++ b/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/Jsh.java @@ -0,0 +1,135 @@ +/* + * 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.dsl.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/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/JshClassLoader.java b/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/JshClassLoader.java new file mode 100644 index 0000000..530ba8f --- /dev/null +++ b/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/JshClassLoader.java @@ -0,0 +1,52 @@ +/* + * 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.dsl.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/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/JshLoaderDelegate.java b/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/JshLoaderDelegate.java new file mode 100644 index 0000000..e50009d --- /dev/null +++ b/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/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.dsl.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/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/JshRoutesBuilderLoader.java b/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/JshRoutesBuilderLoader.java new file mode 100644 index 0000000..7e21669 --- /dev/null +++ b/dsl/camel-jsh-dsl/src/main/java/org/apache/camel/dsl/jsh/JshRoutesBuilderLoader.java @@ -0,0 +1,112 @@ +/* + * 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.dsl.jsh; + +import java.io.Reader; + +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.api.management.ManagedAttribute; +import org.apache.camel.api.management.ManagedResource; +import org.apache.camel.builder.endpoint.EndpointRouteBuilder; +import org.apache.camel.spi.Registry; +import org.apache.camel.spi.Resource; +import org.apache.camel.spi.RoutesBuilderLoader; +import org.apache.camel.spi.annotations.RoutesLoader; +import org.apache.camel.support.RoutesBuilderLoaderSupport; +import org.apache.camel.util.IOHelper; + +/** + * A {@link RoutesBuilderLoader} implementation based on {@link JShell}. + */ +@ManagedResource(description = "Managed JShell RoutesBuilderLoader") +@Experimental +@RoutesLoader("jsh") +public class JshRoutesBuilderLoader extends RoutesBuilderLoaderSupport { + public static final String EXTENSION = "jsh"; + + @ManagedAttribute(description = "Supported file extension") + @Override + public String getSupportedExtension() { + return EXTENSION; + } + + @Override + public RoutesBuilder loadRoutesBuilder(Resource resource) throws Exception { + return EndpointRouteBuilder.loadEndpointRoutesBuilder(resource, JshRoutesBuilderLoader::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/dsl/camel-jsh-dsl/src/test/java/org/apache/camel/dsl/jsh/JshSourceLoaderTest.java b/dsl/camel-jsh-dsl/src/test/java/org/apache/camel/dsl/jsh/JshSourceLoaderTest.java new file mode 100644 index 0000000..e10859f --- /dev/null +++ b/dsl/camel-jsh-dsl/src/test/java/org/apache/camel/dsl/jsh/JshSourceLoaderTest.java @@ -0,0 +1,60 @@ +/* + * 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.dsl.jsh; + +import java.util.Collection; + +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.model.ProcessorDefinition; +import org.apache.camel.model.ToDefinition; +import org.apache.camel.spi.Resource; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JshSourceLoaderTest { + + @ParameterizedTest + @ValueSource(strings = { + "/routes/MyRoute.jsh" + }) + void testLoadRoutes(String location) throws Exception { + try (DefaultCamelContext context = new DefaultCamelContext()) { + Resource resource = context.getResourceLoader().resolveResource(location); + Collection<RoutesBuilder> builders = context.getRoutesLoader().findRoutesBuilders(resource); + + assertThat(builders).hasSize(1); + + RouteBuilder builder = (RouteBuilder) builders.iterator().next(); + builder.setContext(context); + builder.configure(); + + Assertions.assertThat(builder.getRouteCollection().getRoutes()) + .hasSize(1) + .first() + .satisfies(rd -> { + Assertions.assertThat(rd.getInput().getEndpointUri()).matches("timer:.*tick"); + Assertions.assertThat(rd.getOutputs().get(0)).isInstanceOf(ProcessorDefinition.class); + Assertions.assertThat(rd.getOutputs().get(1)).isInstanceOf(ToDefinition.class); + }); + } + } +} diff --git a/dsl/camel-jsh-dsl/src/test/resources/log4j2-test.properties b/dsl/camel-jsh-dsl/src/test/resources/log4j2-test.properties new file mode 100644 index 0000000..55f5c41 --- /dev/null +++ b/dsl/camel-jsh-dsl/src/test/resources/log4j2-test.properties @@ -0,0 +1,31 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +appender.file.type = File +appender.file.name = file +appender.file.fileName = target/camel-jsh-dsl-test.log +appender.file.layout.type = PatternLayout +appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n + +appender.out.type = Console +appender.out.name = out +appender.out.layout.type = PatternLayout +appender.out.layout.pattern = [%30.30t] %-30.30c{1} %-5p %m%n + +rootLogger.level = INFO +rootLogger.appenderRef.file.ref = file +#rootLogger.appenderRef.out.ref = out diff --git a/dsl/camel-jsh-dsl/src/test/resources/routes/MyRoute.jsh b/dsl/camel-jsh-dsl/src/test/resources/routes/MyRoute.jsh new file mode 100644 index 0000000..99bfe4f --- /dev/null +++ b/dsl/camel-jsh-dsl/src/test/resources/routes/MyRoute.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/dsl/pom.xml b/dsl/pom.xml index 592aa6e..4a1224d 100644 --- a/dsl/pom.xml +++ b/dsl/pom.xml @@ -45,6 +45,7 @@ <module>camel-xml-jaxb-dsl-test</module> <module>camel-yaml-dsl</module> <module>camel-js-dsl</module> + <module>camel-jsh-dsl</module> <module>camel-kotlin-dsl</module> <module>camel-kamelet-main</module> <module>camel-jbang</module> diff --git a/parent/pom.xml b/parent/pom.xml index 0ae244a..dfdadc0 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -2809,6 +2809,11 @@ <artifactId>camel-js-dsl</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jsh-dsl</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-kotlin-dsl</artifactId>
