This is an automated email from the ASF dual-hosted git repository. nfilotto pushed a commit to branch 4426/csimple-all-dsl-support in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit fb21d149983b2e9b132282a147e584a3bf2a97fe Author: Nicolas Filotto <[email protected]> AuthorDate: Thu Jan 19 16:39:42 2023 +0100 Ref #4426: Support CSimple expressions with all DSL --- catalog/pom.xml | 26 ++++ .../ROOT/pages/reference/extensions/core.adoc | 4 +- .../org/apache/camel/quarkus/core/CamelConfig.java | 19 +++ .../language}/deployment/pom.xml | 12 +- .../language/deployment/ExpressionBuildItem.java | 43 +++--- .../deployment/LanguageSupportProcessor.java | 87 +++++++++++++ .../language/deployment/dm/DryModeComponent.java | 41 ++---- .../deployment/dm/DryModeComponentResolver.java | 39 ++---- .../language/deployment/dm/DryModeEndpoint.java | 76 +++++++++++ .../language/deployment/dm/DryModeInjector.java | 65 +++++++++ .../language/deployment/dm/DryModeLanguage.java | 98 ++++++++++++++ .../deployment/dm/DryModeLanguageResolver.java | 43 ++++++ .../language/deployment/dm/DryModeMain.java | 83 ++++++++++++ .../language}/pom.xml | 40 ++---- .../language/runtime}/pom.xml | 22 ++-- .../main/resources/META-INF/quarkus-extension.yaml | 27 ++++ extensions-support/pom.xml | 1 + extensions/csimple/deployment/pom.xml | 4 + .../csimple/deployment/CSimpleProcessor.java | 145 +++------------------ .../csimple/deployment/CSimpleXmlProcessor.java | 59 --------- extensions/csimple/runtime/pom.xml | 4 + .../csimple/runtime/src/main/doc/limitations.adoc | 13 +- integration-tests/csimple/pom.xml | 17 +++ .../component/csimple/it/CSimpleResource.java | 8 ++ .../src/main/resources/application.properties | 2 +- .../src/main/resources/routes/my-routes.yaml | 21 +++ .../quarkus/component/csimple/it/CSimpleTest.java | 14 +- poms/bom/pom.xml | 10 ++ poms/bom/src/main/generated/flattened-full-pom.xml | 10 ++ .../src/main/generated/flattened-reduced-pom.xml | 10 ++ .../generated/flattened-reduced-verbose-pom.xml | 10 ++ 31 files changed, 726 insertions(+), 327 deletions(-) diff --git a/catalog/pom.xml b/catalog/pom.xml index 5b741c77b4..4ce7b13aa3 100644 --- a/catalog/pom.xml +++ b/catalog/pom.xml @@ -3698,6 +3698,19 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-support-dsl</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-support-google-cloud</artifactId> @@ -3776,6 +3789,19 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-support-language</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-support-mail</artifactId> diff --git a/docs/modules/ROOT/pages/reference/extensions/core.adoc b/docs/modules/ROOT/pages/reference/extensions/core.adoc index f1c2fa5ef3..04ea0d7962 100644 --- a/docs/modules/ROOT/pages/reference/extensions/core.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/core.adoc @@ -252,9 +252,9 @@ If `true`, basic classes are registered for serialization; otherwise basic class | `boolean` | `false` -|icon:lock[title=Fixed at build time] [[quarkus.camel.csimple.on-build-time-analysis-failure]]`link:#quarkus.camel.csimple.on-build-time-analysis-failure[quarkus.camel.csimple.on-build-time-analysis-failure]` +|icon:lock[title=Fixed at build time] [[quarkus.camel.expression.on-build-time-analysis-failure]]`link:#quarkus.camel.expression.on-build-time-analysis-failure[quarkus.camel.expression.on-build-time-analysis-failure]` -What to do if it is not possible to extract CSimple expressions from a route definition at build time. +What to do if it is not possible to extract expressions from a route definition at build time. | `org.apache.camel.quarkus.core.CamelConfig.FailureRemedy` | `warn` diff --git a/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelConfig.java b/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelConfig.java index 9c62934b18..cedb3bf6e2 100644 --- a/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelConfig.java +++ b/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelConfig.java @@ -63,9 +63,16 @@ public class CamelConfig { /** * Build time configuration options for the Camel CSimple language. */ + @Deprecated(forRemoval = true) @ConfigItem public CSimpleConfig csimple; + /** + * Build time configuration options for the extraction of Camel expressions. + */ + @ConfigItem + public ExpressionConfig expression; + /** * Build time configuration options for the Camel CDI event bridge. */ @@ -358,6 +365,10 @@ public class CamelConfig { public boolean models; } + /** + * @deprecated use {@link ExpressionConfig} instead + */ + @Deprecated(forRemoval = true) @ConfigGroup public static class CSimpleConfig { @@ -366,6 +377,14 @@ public class CamelConfig { public FailureRemedy onBuildTimeAnalysisFailure; } + @ConfigGroup + public static class ExpressionConfig { + + /** What to do if it is not possible to extract expressions from a route definition at build time. */ + @ConfigItem(defaultValue = "warn") + public FailureRemedy onBuildTimeAnalysisFailure; + } + @ConfigGroup public static class EventBridgeConfig { diff --git a/extensions/csimple/deployment/pom.xml b/extensions-support/language/deployment/pom.xml similarity index 84% copy from extensions/csimple/deployment/pom.xml copy to extensions-support/language/deployment/pom.xml index 08e0d33fcd..bfd0f88a0d 100644 --- a/extensions/csimple/deployment/pom.xml +++ b/extensions-support/language/deployment/pom.xml @@ -21,13 +21,13 @@ <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-csimple-parent</artifactId> + <artifactId>camel-quarkus-support-language-parent</artifactId> <version>2.16.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> - <artifactId>camel-quarkus-csimple-deployment</artifactId> - <name>Camel Quarkus :: CSimple :: Deployment</name> + <artifactId>camel-quarkus-support-language-deployment</artifactId> + <name>Camel Quarkus :: Support :: Language :: Deployment</name> <dependencies> <dependency> @@ -36,7 +36,11 @@ </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-csimple</artifactId> + <artifactId>camel-quarkus-support-language</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-main</artifactId> </dependency> </dependencies> diff --git a/integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/ExpressionBuildItem.java similarity index 50% copy from integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java copy to extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/ExpressionBuildItem.java index 4e3d3bb18d..f71a11728d 100644 --- a/integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java +++ b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/ExpressionBuildItem.java @@ -14,36 +14,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.csimple.it; +package org.apache.camel.quarkus.support.language.deployment; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import io.restassured.http.ContentType; -import org.junit.jupiter.api.Test; +import io.quarkus.builder.item.MultiBuildItem; -import static org.hamcrest.Matchers.is; +public final class ExpressionBuildItem extends MultiBuildItem { -@QuarkusTest -class CSimpleTest { + final String language; + final String expression; + final boolean predicate; - @Test - public void csimpleHello() { - RestAssured.given() - .body("Joe") - .contentType(ContentType.TEXT) - .post("/csimple/csimple-hello") - .then() - .body(is("Hello Joe")); + public ExpressionBuildItem(String language, String expression, boolean predicate) { + this.language = language; + this.expression = expression; + this.predicate = predicate; } - @Test - public void csimpleXml() { - RestAssured.given() - .body("Joe") - .contentType(ContentType.TEXT) - .post("/csimple/csimple-xml-dsl") - .then() - .body(is("Hi Joe")); + public String getLanguage() { + return language; } + public String getExpression() { + return expression; + } + + public boolean isPredicate() { + return predicate; + } } diff --git a/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/LanguageSupportProcessor.java b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/LanguageSupportProcessor.java new file mode 100644 index 0000000000..ddf5b29cfa --- /dev/null +++ b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/LanguageSupportProcessor.java @@ -0,0 +1,87 @@ +/* + * 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.quarkus.support.language.deployment; + +import java.util.ArrayList; +import java.util.List; + +import io.quarkus.bootstrap.classloading.QuarkusClassLoader; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.quarkus.core.CamelConfig; +import org.apache.camel.quarkus.core.deployment.spi.CamelRoutesBuilderClassBuildItem; +import org.apache.camel.quarkus.support.language.deployment.dm.DryModeLanguage; +import org.apache.camel.quarkus.support.language.deployment.dm.DryModeMain; +import org.jboss.logging.Logger; + +class LanguageSupportProcessor { + + private static final Logger LOG = Logger.getLogger(LanguageSupportProcessor.class); + + @BuildStep + void extractExpressions(CamelConfig config, List<CamelRoutesBuilderClassBuildItem> routesBuilderClasses, + BuildProducer<ExpressionBuildItem> producer) throws Exception { + final ClassLoader loader = Thread.currentThread().getContextClassLoader(); + if (!(loader instanceof QuarkusClassLoader)) { + throw new IllegalStateException( + QuarkusClassLoader.class.getSimpleName() + " expected as the context class loader"); + } + final List<Class<?>> routeBuilderClasses = new ArrayList<>(routesBuilderClasses.size()); + for (CamelRoutesBuilderClassBuildItem routesBuilderClass : routesBuilderClasses) { + final String className = routesBuilderClass.getDotName().toString(); + final Class<?> cl = loader.loadClass(className); + + if (RouteBuilder.class.isAssignableFrom(cl)) { + routeBuilderClasses.add(cl); + } else { + LOG.warnf("CSimple language expressions occurring in %s won't be compiled at build time", cl); + } + } + try { + DryModeMain main = new DryModeMain("Expression Extractor", routeBuilderClasses.toArray(new Class<?>[0])); + main.start(); + main.run(); + for (DryModeLanguage language : main.getLanguages()) { + final String name = language.getName(); + for (String exp : language.getPredicates()) { + producer.produce(new ExpressionBuildItem(name, exp, true)); + } + for (String exp : language.getExpressions()) { + producer.produce(new ExpressionBuildItem(name, exp, false)); + } + } + } catch (Exception e) { + switch (config.expression.onBuildTimeAnalysisFailure) { + case fail: + throw new RuntimeException( + "Could not extract language expressions." + + "You may want to set quarkus.camel.expression.on-build-time-analysis-failure to warn or ignore if you do not use languages in your routes", + e); + case warn: + LOG.warn("Could not extract language expressions.", e); + break; + case ignore: + LOG.debug("Could not extract language expressions", e); + break; + default: + throw new IllegalStateException("Unexpected " + CamelConfig.FailureRemedy.class.getSimpleName() + ": " + + config.expression.onBuildTimeAnalysisFailure); + } + } + } +} diff --git a/integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeComponent.java similarity index 50% copy from integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java copy to extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeComponent.java index 4e3d3bb18d..3586ec36f8 100644 --- a/integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java +++ b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeComponent.java @@ -14,36 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.csimple.it; +package org.apache.camel.quarkus.support.language.deployment.dm; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import io.restassured.http.ContentType; -import org.junit.jupiter.api.Test; +import java.util.Map; -import static org.hamcrest.Matchers.is; +import org.apache.camel.Endpoint; +import org.apache.camel.spi.annotations.Component; +import org.apache.camel.support.DefaultComponent; -@QuarkusTest -class CSimpleTest { - - @Test - public void csimpleHello() { - RestAssured.given() - .body("Joe") - .contentType(ContentType.TEXT) - .post("/csimple/csimple-hello") - .then() - .body(is("Hello Joe")); - } +/** + * {@code DryModeComponent} is a mock component that is used as replacement of all components in the routes for a dry + * run. + */ +@Component("dm") +public class DryModeComponent extends DefaultComponent { - @Test - public void csimpleXml() { - RestAssured.given() - .body("Joe") - .contentType(ContentType.TEXT) - .post("/csimple/csimple-xml-dsl") - .then() - .body(is("Hi Joe")); + @Override + protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) { + return new DryModeEndpoint(uri); } - } diff --git a/integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeComponentResolver.java similarity index 50% copy from integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java copy to extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeComponentResolver.java index 4e3d3bb18d..98dbce3311 100644 --- a/integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java +++ b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeComponentResolver.java @@ -14,36 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.csimple.it; +package org.apache.camel.quarkus.support.language.deployment.dm; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import io.restassured.http.ContentType; -import org.junit.jupiter.api.Test; +import org.apache.camel.CamelContext; +import org.apache.camel.Component; +import org.apache.camel.spi.ComponentResolver; -import static org.hamcrest.Matchers.is; - -@QuarkusTest -class CSimpleTest { - - @Test - public void csimpleHello() { - RestAssured.given() - .body("Joe") - .contentType(ContentType.TEXT) - .post("/csimple/csimple-hello") - .then() - .body(is("Hello Joe")); - } +/** + * {@code DryModeComponentResolver} is used to resolve all components with {@link DryModeComponent} for a dry run. + */ +class DryModeComponentResolver implements ComponentResolver { - @Test - public void csimpleXml() { - RestAssured.given() - .body("Joe") - .contentType(ContentType.TEXT) - .post("/csimple/csimple-xml-dsl") - .then() - .body(is("Hi Joe")); + @Override + public Component resolveComponent(String name, CamelContext context) { + return new DryModeComponent(); } - } diff --git a/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeEndpoint.java b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeEndpoint.java new file mode 100644 index 0000000000..87b79765c0 --- /dev/null +++ b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeEndpoint.java @@ -0,0 +1,76 @@ +/* + * 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.quarkus.support.language.deployment.dm; + +import org.apache.camel.Category; +import org.apache.camel.Consumer; +import org.apache.camel.Endpoint; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.spi.UriEndpoint; +import org.apache.camel.support.DefaultConsumer; +import org.apache.camel.support.DefaultEndpoint; +import org.apache.camel.support.DefaultProducer; + +/** + * {@code DryModeEndpoint} is a mock endpoint that is used as replacement of all endpoints in the routes for a dry run. + */ +@UriEndpoint(firstVersion = "3.20.0", scheme = "dm", title = "Dry Mode", syntax = "dm:name", category = { Category.CORE, + Category.TESTING }, lenientProperties = true) +public class DryModeEndpoint extends DefaultEndpoint { + + private final String uri; + + public DryModeEndpoint(String uri) { + this.uri = uri; + } + + @Override + public Producer createProducer() { + return new DryModeProducer(this); + } + + @Override + public Consumer createConsumer(Processor processor) { + return new DryModeConsumer(this, processor); + } + + @Override + protected String createEndpointUri() { + return String.format("dm:%s", uri); + } + + private static class DryModeConsumer extends DefaultConsumer { + + DryModeConsumer(Endpoint endpoint, Processor processor) { + super(endpoint, processor); + } + } + + private static class DryModeProducer extends DefaultProducer { + + DryModeProducer(Endpoint endpoint) { + super(endpoint); + } + + @Override + public void process(Exchange exchange) { + // Nothing to do + } + } +} diff --git a/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeInjector.java b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeInjector.java new file mode 100644 index 0000000000..46d53c058f --- /dev/null +++ b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeInjector.java @@ -0,0 +1,65 @@ +/* + * 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.quarkus.support.language.deployment.dm; + +import org.apache.camel.Component; +import org.apache.camel.spi.Injector; + +/** + * {@code DryModeInjector} is used to replace instantiations of any component with an instantiation of + * {@link DryModeComponent} for a dry run. + */ +class DryModeInjector implements Injector { + + private final Injector delegate; + + DryModeInjector(Injector delegate) { + this.delegate = delegate; + } + + @SuppressWarnings("unchecked") + @Override + public <T> T newInstance(Class<T> type) { + if (Component.class.isAssignableFrom(type)) { + return (T) delegate.newInstance(DryModeComponent.class); + } + return delegate.newInstance(type); + } + + @SuppressWarnings("unchecked") + @Override + public <T> T newInstance(Class<T> type, String factoryMethod) { + if (Component.class.isAssignableFrom(type)) { + return (T) delegate.newInstance(DryModeComponent.class); + } + return delegate.newInstance(type, factoryMethod); + } + + @SuppressWarnings("unchecked") + @Override + public <T> T newInstance(Class<T> type, boolean postProcessBean) { + if (Component.class.isAssignableFrom(type)) { + return (T) delegate.newInstance(DryModeComponent.class); + } + return delegate.newInstance(type, postProcessBean); + } + + @Override + public boolean supportsAutoWiring() { + return delegate.supportsAutoWiring(); + } +} diff --git a/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeLanguage.java b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeLanguage.java new file mode 100644 index 0000000000..cee5ca0b84 --- /dev/null +++ b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeLanguage.java @@ -0,0 +1,98 @@ +/* + * 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.quarkus.support.language.deployment.dm; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.Expression; +import org.apache.camel.Predicate; +import org.apache.camel.spi.Language; + +/** + * {@code DryModeLanguage} is a mock language meant to collect all the expressions and predicates that are registered + * for a specific language. + */ +public class DryModeLanguage implements Language { + + private final String name; + private final Predicate defaultPredicate = new DryModePredicate(); + private final Expression defaultExpression = new DryModeExpression(); + private final Map<Boolean, Set<String>> expressions = new ConcurrentHashMap<>(); + + public DryModeLanguage(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public Set<String> getPredicates() { + return expressions.getOrDefault(Boolean.TRUE, Set.of()); + } + + public Set<String> getExpressions() { + return expressions.getOrDefault(Boolean.FALSE, Set.of()); + } + + @Override + public Predicate createPredicate(String expression) { + expressions.computeIfAbsent(Boolean.TRUE, mode -> ConcurrentHashMap.newKeySet()).add(expression); + return defaultPredicate; + } + + @Override + public Expression createExpression(String expression) { + expressions.computeIfAbsent(Boolean.FALSE, mode -> ConcurrentHashMap.newKeySet()).add(expression); + return defaultExpression; + } + + private static class DryModePredicate implements Predicate { + + @Override + public boolean matches(Exchange exchange) { + return false; + } + + @Override + public void init(CamelContext context) { + // nothing to do + } + + @Override + public void initPredicate(CamelContext context) { + // nothing to do + } + } + + private static class DryModeExpression implements Expression { + + @Override + public <T> T evaluate(Exchange exchange, Class<T> type) { + return null; + } + + @Override + public void init(CamelContext context) { + // nothing to do + } + } +} diff --git a/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeLanguageResolver.java b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeLanguageResolver.java new file mode 100644 index 0000000000..ae1a91a237 --- /dev/null +++ b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeLanguageResolver.java @@ -0,0 +1,43 @@ +/* + * 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.quarkus.support.language.deployment.dm; + +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.camel.CamelContext; +import org.apache.camel.NoSuchLanguageException; +import org.apache.camel.spi.Language; +import org.apache.camel.spi.LanguageResolver; + +/** + * {@code DryModeLanguageResolver} is used to resolve all languages with {@link DryModeLanguage} for a dry run. + */ +class DryModeLanguageResolver implements LanguageResolver { + + private final Map<String, DryModeLanguage> languages = new ConcurrentHashMap<>(); + + @Override + public Language resolveLanguage(String name, CamelContext context) throws NoSuchLanguageException { + return languages.computeIfAbsent(name, DryModeLanguage::new); + } + + Collection<DryModeLanguage> getLanguages() { + return languages.values(); + } +} diff --git a/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeMain.java b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeMain.java new file mode 100644 index 0000000000..2eb553eed3 --- /dev/null +++ b/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/dm/DryModeMain.java @@ -0,0 +1,83 @@ +/* + * 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.quarkus.support.language.deployment.dm; + +import java.util.Collection; + +import org.apache.camel.CamelContext; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.main.MainSupport; + +/** + * {@code DryModeMain} a specific main implementation allowing to do a dry run of the application in order to collect + * the expressions defined in all the routes of the project. + */ +public class DryModeMain extends MainSupport { + + private final DryModeLanguageResolver languageResolver = new DryModeLanguageResolver(); + + public DryModeMain(String appName, Class<?>[] routeBuilderClasses) { + setAppName(appName); + mainConfigurationProperties.addRoutesBuilder(routeBuilderClasses); + } + + @Override + protected ProducerTemplate findOrCreateCamelTemplate() { + final CamelContext context = getCamelContext(); + if (context == null) { + return null; + } + return context.createProducerTemplate(); + } + + @Override + protected CamelContext createCamelContext() { + DefaultCamelContext ctx = new DefaultCamelContext(false); + ctx.setName(getAppName()); + ctx.setLanguageResolver(languageResolver); + ctx.setComponentResolver(new DryModeComponentResolver()); + ctx.setInjector(new DryModeInjector(ctx.getInjector())); + return ctx; + } + + @Override + protected void doInit() throws Exception { + // turn off auto-wiring when running in dry mode + mainConfigurationProperties.setAutowiredEnabled(false); + // and turn off fail fast as we stub components + mainConfigurationProperties.setAutoConfigurationFailFast(false); + mainConfigurationProperties.setAutoStartup(false); + mainConfigurationProperties.setDurationMaxSeconds(1); + mainConfigurationProperties.setAutoConfigurationLogSummary(false); + super.doInit(); + initCamelContext(); + } + + @Override + protected void doStart() throws Exception { + super.doStart(); + CamelContext context = getCamelContext(); + if (context != null) { + context.start(); + } + } + + public Collection<DryModeLanguage> getLanguages() { + return languageResolver.getLanguages(); + } +} diff --git a/extensions/csimple/deployment/pom.xml b/extensions-support/language/pom.xml similarity index 51% copy from extensions/csimple/deployment/pom.xml copy to extensions-support/language/pom.xml index 08e0d33fcd..bf35edaeb1 100644 --- a/extensions/csimple/deployment/pom.xml +++ b/extensions-support/language/pom.xml @@ -21,41 +21,17 @@ <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-csimple-parent</artifactId> + <artifactId>camel-quarkus-extensions-support</artifactId> <version>2.16.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> - <artifactId>camel-quarkus-csimple-deployment</artifactId> - <name>Camel Quarkus :: CSimple :: Deployment</name> - - <dependencies> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-core-deployment</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-csimple</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> + <artifactId>camel-quarkus-support-language-parent</artifactId> + <name>Camel Quarkus :: Support :: Language</name> + <packaging>pom</packaging> + <modules> + <module>deployment</module> + <module>runtime</module> + </modules> </project> diff --git a/extensions/csimple/deployment/pom.xml b/extensions-support/language/runtime/pom.xml similarity index 78% copy from extensions/csimple/deployment/pom.xml copy to extensions-support/language/runtime/pom.xml index 08e0d33fcd..bacccacecd 100644 --- a/extensions/csimple/deployment/pom.xml +++ b/extensions-support/language/runtime/pom.xml @@ -21,27 +21,32 @@ <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-csimple-parent</artifactId> + <artifactId>camel-quarkus-support-language-parent</artifactId> <version>2.16.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> - <artifactId>camel-quarkus-csimple-deployment</artifactId> - <name>Camel Quarkus :: CSimple :: Deployment</name> + <artifactId>camel-quarkus-support-language</artifactId> + <name>Camel Quarkus :: Support :: Language :: Runtime</name> + + <properties> + <camel.quarkus.jvmSince>2.16.0</camel.quarkus.jvmSince> + <camel.quarkus.nativeSince>2.16.0</camel.quarkus.nativeSince> + </properties> <dependencies> <dependency> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-core-deployment</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-csimple</artifactId> + <artifactId>camel-quarkus-core</artifactId> </dependency> </dependencies> <build> <plugins> + <plugin> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-extension-maven-plugin</artifactId> + </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> @@ -57,5 +62,4 @@ </plugin> </plugins> </build> - </project> diff --git a/extensions-support/language/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions-support/language/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 0000000000..d26424ad1f --- /dev/null +++ b/extensions-support/language/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -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. +# + +--- +name: "Camel Quarkus Support Language" +description: "Camel Quarkus Support Language" +metadata: + unlisted: true + keywords: + - "camel" + guide: "https://quarkus.io/guides/camel" + categories: + - "integration" diff --git a/extensions-support/pom.xml b/extensions-support/pom.xml index f73d773030..9d85164e5a 100644 --- a/extensions-support/pom.xml +++ b/extensions-support/pom.xml @@ -50,6 +50,7 @@ <module>jackson-dataformat-xml</module> <module>jdbc</module> <module>jetty</module> + <module>language</module> <module>mail</module> <module>mongodb</module> <module>reactor-netty</module> diff --git a/extensions/csimple/deployment/pom.xml b/extensions/csimple/deployment/pom.xml index 08e0d33fcd..389fda0ee2 100644 --- a/extensions/csimple/deployment/pom.xml +++ b/extensions/csimple/deployment/pom.xml @@ -34,6 +34,10 @@ <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-core-deployment</artifactId> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-support-language-deployment</artifactId> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-csimple</artifactId> diff --git a/extensions/csimple/deployment/src/main/java/org/apache/camel/quarkus/component/csimple/deployment/CSimpleProcessor.java b/extensions/csimple/deployment/src/main/java/org/apache/camel/quarkus/component/csimple/deployment/CSimpleProcessor.java index 500d73b995..92a0a77204 100644 --- a/extensions/csimple/deployment/src/main/java/org/apache/camel/quarkus/component/csimple/deployment/CSimpleProcessor.java +++ b/extensions/csimple/deployment/src/main/java/org/apache/camel/quarkus/component/csimple/deployment/CSimpleProcessor.java @@ -20,7 +20,6 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -34,17 +33,12 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeSet; -import java.util.function.BiConsumer; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Marshaller.Listener; - import io.quarkus.bootstrap.classloading.ClassPathElement; import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.deployment.annotations.BuildProducer; @@ -60,33 +54,24 @@ import io.quarkus.deployment.dev.JavaCompilationProvider; import io.quarkus.deployment.pkg.builditem.BuildSystemTargetBuildItem; import io.quarkus.deployment.recording.RecorderContext; import io.quarkus.runtime.RuntimeValue; -import org.apache.camel.CamelContext; import org.apache.camel.Exchange; -import org.apache.camel.NamedNode; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.language.csimple.CSimpleCodeGenerator; import org.apache.camel.language.csimple.CSimpleGeneratedCode; import org.apache.camel.language.csimple.CSimpleHelper; import org.apache.camel.language.csimple.CSimpleLanguage; import org.apache.camel.language.csimple.CSimpleLanguage.Builder; -import org.apache.camel.model.Constants; -import org.apache.camel.model.ExpressionNode; import org.apache.camel.quarkus.component.csimple.CSimpleLanguageRecorder; -import org.apache.camel.quarkus.core.CamelConfig; -import org.apache.camel.quarkus.core.CamelConfig.FailureRemedy; -import org.apache.camel.quarkus.core.deployment.LanguageExpressionContentHandler; import org.apache.camel.quarkus.core.deployment.spi.CamelBeanBuildItem; import org.apache.camel.quarkus.core.deployment.spi.CamelContextBuildItem; -import org.apache.camel.quarkus.core.deployment.spi.CamelRoutesBuilderClassBuildItem; import org.apache.camel.quarkus.core.deployment.spi.CompiledCSimpleExpressionBuildItem; import org.apache.camel.quarkus.core.util.FileUtils; +import org.apache.camel.quarkus.support.language.deployment.ExpressionBuildItem; import org.apache.camel.util.PropertiesHelper; -import org.jboss.logging.Logger; class CSimpleProcessor { - private static final Logger LOG = Logger.getLogger(CSimpleProcessor.class); + private static final String CLASS_NAME = "CompiledExpression"; + private static final String PACKAGE_NAME = "org.apache.camel.quarkus.component.csimple.generated"; static final String CLASS_EXT = ".class"; private static final String FEATURE = "camel-csimple"; @@ -97,71 +82,17 @@ class CSimpleProcessor { @BuildStep void collectCSimpleExpressions( - CamelConfig config, - List<CamelRoutesBuilderClassBuildItem> routesBuilderClasses, - BuildProducer<CSimpleExpressionSourceBuildItem> csimpleExpressions) - throws ClassNotFoundException { - - if (!routesBuilderClasses.isEmpty()) { - final ClassLoader loader = Thread.currentThread().getContextClassLoader(); - if (!(loader instanceof QuarkusClassLoader)) { - throw new IllegalStateException( - QuarkusClassLoader.class.getSimpleName() + " expected as the context class loader"); - } - - final ExpressionCollector collector = new ExpressionCollector(loader); - - final CamelContext ctx = new DefaultCamelContext(); - for (CamelRoutesBuilderClassBuildItem routesBuilderClass : routesBuilderClasses) { - final String className = routesBuilderClass.getDotName().toString(); - final Class<?> cl = loader.loadClass(className); - - if (!RouteBuilder.class.isAssignableFrom(cl)) { - LOG.warnf("CSimple language expressions occurring in %s won't be compiled at build time", cl); - } else { - try { - final RouteBuilder rb = (RouteBuilder) cl.getDeclaredConstructor().newInstance(); - rb.setCamelContext(ctx); - try { - rb.configure(); - collector.collect( - "csimple", - (script, isPredicate) -> csimpleExpressions.produce( - new CSimpleExpressionSourceBuildItem( - script, - isPredicate, - className)), - rb.getRouteCollection(), - rb.getRestCollection()); - - } catch (Exception e) { - switch (config.csimple.onBuildTimeAnalysisFailure) { - case fail: - throw new RuntimeException( - "Could not extract CSimple expressions from " + className - + ". You may want to set quarkus.camel.csimple.on-build-time-analysis-failure to warn or ignore if you do not use CSimple language in your routes", - e); - case warn: - LOG.warnf(e, - "Could not extract CSimple language expressions from the route definition %s in class %s.", - rb, cl); - break; - case ignore: - LOG.debugf(e, - "Could not extract CSimple language expressions from the route definition %s in class %s", - rb, cl); - break; - default: - throw new IllegalStateException("Unexpected " + FailureRemedy.class.getSimpleName() + ": " - + config.csimple.onBuildTimeAnalysisFailure); - } - } - - } catch (InstantiationException | IllegalAccessException | NoSuchMethodException - | InvocationTargetException e) { - throw new RuntimeException("Could not instantiate " + className, e); - } - } + List<ExpressionBuildItem> expressions, + BuildProducer<CSimpleExpressionSourceBuildItem> csimpleExpressions) { + + int counter = 0; + for (ExpressionBuildItem expression : expressions) { + if ("csimple".equals(expression.getLanguage())) { + csimpleExpressions.produce( + new CSimpleExpressionSourceBuildItem( + expression.getExpression(), + expression.isPredicate(), + String.format("%s.%s_%d", PACKAGE_NAME, CLASS_NAME, ++counter))); } } } @@ -303,8 +234,8 @@ class CSimpleProcessor { Set<File> classPathElements = Stream.of(CSimpleHelper.class, Exchange.class, PropertiesHelper.class) .map(clazz -> clazz.getName().replace('.', '/') + CLASS_EXT) .flatMap(className -> (Stream<ClassPathElement>) quarkusClassLoader.getElementsWithResource(className).stream()) - .map(cpe -> cpe.getRoot()) - .filter(p -> p != null) + .map(ClassPathElement::getRoot) + .filter(Objects::nonNull) .map(Path::toFile) .collect(Collectors.toSet()); @@ -324,46 +255,4 @@ class CSimpleProcessor { Collections.emptyList()); } - /** - * Collects expressions of a given language. - */ - static class ExpressionCollector { - private final JAXBContext jaxbContext; - private final Marshaller marshaller; - - ExpressionCollector(ClassLoader loader) { - try { - jaxbContext = JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES, loader); - Marshaller m = jaxbContext.createMarshaller(); - m.setListener(new RouteDefinitionNormalizer()); - marshaller = m; - } catch (JAXBException e) { - throw new RuntimeException("Could not creat a JAXB marshaler", e); - } - } - - public void collect(String languageName, BiConsumer<String, Boolean> expressionConsumer, NamedNode... nodes) { - final LanguageExpressionContentHandler handler = new LanguageExpressionContentHandler(languageName, - expressionConsumer); - for (NamedNode node : nodes) { - try { - marshaller.marshal(node, handler); - } catch (JAXBException e) { - throw new RuntimeException("Could not collect '" + languageName + "' expressions from node " + node, e); - } - } - } - - /** - * Inlines all fancy expression builders so that JAXB can serialize the model properly. - */ - private static class RouteDefinitionNormalizer extends Listener { - public void beforeMarshal(Object source) { - if (source instanceof ExpressionNode) { - ((ExpressionNode) source).preCreateProcessor(); - } - } - } - } - } diff --git a/extensions/csimple/deployment/src/main/java/org/apache/camel/quarkus/component/csimple/deployment/CSimpleXmlProcessor.java b/extensions/csimple/deployment/src/main/java/org/apache/camel/quarkus/component/csimple/deployment/CSimpleXmlProcessor.java deleted file mode 100644 index 17010f45fe..0000000000 --- a/extensions/csimple/deployment/src/main/java/org/apache/camel/quarkus/component/csimple/deployment/CSimpleXmlProcessor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.quarkus.component.csimple.deployment; - -import java.io.FileNotFoundException; -import java.io.InputStream; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import io.quarkus.deployment.annotations.BuildProducer; -import io.quarkus.deployment.annotations.BuildStep; -import org.apache.camel.quarkus.core.deployment.LanguageExpressionContentHandler; -import org.apache.camel.quarkus.core.deployment.main.CamelMainHelper; -import org.jboss.logging.Logger; - -public class CSimpleXmlProcessor { - private static final Logger LOG = Logger.getLogger(CSimpleXmlProcessor.class); - - @BuildStep - void collectCSimpleExpresions(BuildProducer<CSimpleExpressionSourceBuildItem> csimpleExpressions) throws Exception { - final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); - saxParserFactory.setNamespaceAware(true); - final SAXParser saxParser = saxParserFactory.newSAXParser(); - - CamelMainHelper.forEachMatchingResource( - resource -> { - try (InputStream is = resource.getInputStream()) { - saxParser.parse( - is, - new LanguageExpressionContentHandler( - "csimple", - (script, isPredicate) -> csimpleExpressions.produce( - new CSimpleExpressionSourceBuildItem( - script, - isPredicate, - "org.apache.camel.language.csimple.XmlRouteBuilder")))); - } catch (FileNotFoundException e) { - LOG.debugf("No XML routes found in %s. Skipping XML routes detection.", resource.getLocation()); - } catch (Exception e) { - throw new RuntimeException("Could not analyze CSimple expressions in " + resource.getLocation(), e); - } - }); - } -} diff --git a/extensions/csimple/runtime/pom.xml b/extensions/csimple/runtime/pom.xml index 866b1e6d73..b0c6132955 100644 --- a/extensions/csimple/runtime/pom.xml +++ b/extensions/csimple/runtime/pom.xml @@ -41,6 +41,10 @@ <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-core</artifactId> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-support-language</artifactId> + </dependency> </dependencies> <build> diff --git a/extensions/csimple/runtime/src/main/doc/limitations.adoc b/extensions/csimple/runtime/src/main/doc/limitations.adoc index 115ae917e9..240169c1c9 100644 --- a/extensions/csimple/runtime/src/main/doc/limitations.adoc +++ b/extensions/csimple/runtime/src/main/doc/limitations.adoc @@ -1,15 +1,6 @@ -CSimple language is supported only in +CSimple language is supported in all existing DSL, but be aware that to extract the expressions from the existing routes, a dry run is done during the startup in JVM mode or during the build in the Native mode which adds some log entries that you can simply ignore. -* XML DSL -* Java DSL when implemented in a class extending `org.apache.camel.builder.RouteBuilder` - -The compilation of CSimple scripts happens at build time. To be able to discover the scripts in the route definitions, -those definitions need to get assembled at build time. When extending -`org.apache.camel.builder.RouteBuilder`, this basically means instantiating your `RouteBuilder`, setting -a fake `CamelContext` instance on it and calling its `configure()` method. It may fail if your `configure()` -method attempts to access some resource that is only available at runtime. - -You can use the `quarkus.camel.csimple.on-build-time-analysis-failure` configuration parameter to decide +You can use the `quarkus.camel.expression.on-build-time-analysis-failure` configuration parameter to decide what should happen in such cases. Possible values are `warn` (default), `fail` or `ignore`. [WARNING] diff --git a/integration-tests/csimple/pom.xml b/integration-tests/csimple/pom.xml index 1f802b7e84..9b45524a3b 100644 --- a/integration-tests/csimple/pom.xml +++ b/integration-tests/csimple/pom.xml @@ -47,6 +47,10 @@ <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-xml-io-dsl</artifactId> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-yaml-dsl</artifactId> + </dependency> <!-- test dependencies --> <dependency> @@ -137,6 +141,19 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-yaml-dsl-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> </dependencies> </profile> </profiles> diff --git a/integration-tests/csimple/src/main/java/org/apache/camel/quarkus/component/csimple/it/CSimpleResource.java b/integration-tests/csimple/src/main/java/org/apache/camel/quarkus/component/csimple/it/CSimpleResource.java index 7cae63469e..f836df6792 100644 --- a/integration-tests/csimple/src/main/java/org/apache/camel/quarkus/component/csimple/it/CSimpleResource.java +++ b/integration-tests/csimple/src/main/java/org/apache/camel/quarkus/component/csimple/it/CSimpleResource.java @@ -48,4 +48,12 @@ public class CSimpleResource { public String csimpleXmlDsl(String body) { return producerTemplate.requestBody("direct:csimple-xml-dsl", body, String.class); } + + @Path("/csimple-yaml-dsl") + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String csimpleYamlDsl(String body) { + return producerTemplate.requestBody("direct:csimple-yaml-dsl", body, String.class); + } } diff --git a/integration-tests/csimple/src/main/resources/application.properties b/integration-tests/csimple/src/main/resources/application.properties index 5a35e452dd..940bc7645b 100644 --- a/integration-tests/csimple/src/main/resources/application.properties +++ b/integration-tests/csimple/src/main/resources/application.properties @@ -15,4 +15,4 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -camel.main.routes-include-pattern = classpath:routes/my-routes.xml +camel.main.routes-include-pattern = classpath:routes/my-routes.xml,classpath:routes/my-routes.yaml diff --git a/integration-tests/csimple/src/main/resources/routes/my-routes.yaml b/integration-tests/csimple/src/main/resources/routes/my-routes.yaml new file mode 100644 index 0000000000..23177d2697 --- /dev/null +++ b/integration-tests/csimple/src/main/resources/routes/my-routes.yaml @@ -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. +# +- from: + uri: "direct:csimple-yaml-dsl" + steps: + - set-body: + csimple: "Bonjour ${body}" \ No newline at end of file diff --git a/integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java b/integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java index 4e3d3bb18d..1a4fd2e94d 100644 --- a/integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java +++ b/integration-tests/csimple/src/test/java/org/apache/camel/quarkus/component/csimple/it/CSimpleTest.java @@ -27,7 +27,7 @@ import static org.hamcrest.Matchers.is; class CSimpleTest { @Test - public void csimpleHello() { + void csimpleHello() { RestAssured.given() .body("Joe") .contentType(ContentType.TEXT) @@ -37,7 +37,7 @@ class CSimpleTest { } @Test - public void csimpleXml() { + void csimpleXml() { RestAssured.given() .body("Joe") .contentType(ContentType.TEXT) @@ -46,4 +46,14 @@ class CSimpleTest { .body(is("Hi Joe")); } + @Test + void csimpleYaml() { + RestAssured.given() + .body("John") + .contentType(ContentType.TEXT) + .post("/csimple/csimple-yaml-dsl") + .then() + .body(is("Bonjour John")); + } + } diff --git a/poms/bom/pom.xml b/poms/bom/pom.xml index 1abb991961..8da7cafaf1 100644 --- a/poms/bom/pom.xml +++ b/poms/bom/pom.xml @@ -9039,6 +9039,16 @@ <artifactId>camel-quarkus-support-jetty-deployment</artifactId> <version>${camel-quarkus.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-support-language</artifactId> + <version>${camel-quarkus.version}</version> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-support-language-deployment</artifactId> + <version>${camel-quarkus.version}</version> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-support-mail</artifactId> diff --git a/poms/bom/src/main/generated/flattened-full-pom.xml b/poms/bom/src/main/generated/flattened-full-pom.xml index 5ef1314731..363ccc85f5 100644 --- a/poms/bom/src/main/generated/flattened-full-pom.xml +++ b/poms/bom/src/main/generated/flattened-full-pom.xml @@ -8976,6 +8976,16 @@ <artifactId>camel-quarkus-support-jetty-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> <version>2.16.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + <artifactId>camel-quarkus-support-language</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + <version>2.16.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + <artifactId>camel-quarkus-support-language-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + <version>2.16.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> <artifactId>camel-quarkus-support-mail</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> diff --git a/poms/bom/src/main/generated/flattened-reduced-pom.xml b/poms/bom/src/main/generated/flattened-reduced-pom.xml index e83b23fd6a..bddedf1144 100644 --- a/poms/bom/src/main/generated/flattened-reduced-pom.xml +++ b/poms/bom/src/main/generated/flattened-reduced-pom.xml @@ -8971,6 +8971,16 @@ <artifactId>camel-quarkus-support-jetty-deployment</artifactId> <version>2.16.0-SNAPSHOT</version> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-support-language</artifactId> + <version>2.16.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-support-language-deployment</artifactId> + <version>2.16.0-SNAPSHOT</version> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-support-mail</artifactId> diff --git a/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml b/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml index b64268cb5f..724ec208b7 100644 --- a/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml +++ b/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml @@ -8971,6 +8971,16 @@ <artifactId>camel-quarkus-support-jetty-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> <version>2.16.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + <artifactId>camel-quarkus-support-language</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + <version>2.16.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + <artifactId>camel-quarkus-support-language-deployment</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + <version>2.16.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} --> <artifactId>camel-quarkus-support-mail</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
