This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch tod in repository https://gitbox.apache.org/repos/asf/camel.git
commit 9f533c566ea45bb13a8346350758496b02b5d727 Author: Claus Ibsen <[email protected]> AuthorDate: Wed Oct 8 13:06:19 2025 +0200 CAMEL-22507: camel-jbang - When using kamelets with dynamic EIPs such as toD then we need to resolve the kamelet name during export to ensure we can gather dependencies and kamelet spec files to be included in the export. --- .../org/apache/camel/spi/ComponentResolver.java | 3 +- ...solver.java => OptimisedComponentResolver.java} | 17 +++--- .../camel/impl/engine/AbstractCamelContext.java | 4 ++ .../engine/DefaultOptimisedComponentResolver.java} | 33 +++++++----- .../camel/impl/engine/SimpleCamelContext.java | 14 +++-- .../java/org/apache/camel/processor/Enricher.java | 1 + .../org/apache/camel/processor/PollEnricher.java | 7 ++- .../camel/processor/SendDynamicProcessor.java | 7 ++- .../org/apache/camel/support/ExchangeHelper.java | 16 ++++++ .../camel/dsl/jbang/core/commands/ExportTest.java | 47 +++++++++++++++++ .../src/test/resources/cheese-sink.kamelet.yaml | 51 ++++++++++++++++++ .../src/test/resources/toDroute.yaml | 24 +++++++++ .../java/org/apache/camel/main/KameletMain.java | 4 ++ .../KameletOptimisedComponentResolver.java | 61 ++++++++++++++++++++++ 14 files changed, 256 insertions(+), 33 deletions(-) diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java b/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java index 3d3f56ba529e..d836a74ff526 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java @@ -20,8 +20,7 @@ import org.apache.camel.CamelContext; import org.apache.camel.Component; /** - * Represents a resolver of components from a URI to be able to auto-load them using some discovery mechanism like - * {@link org.apache.camel.impl.DefaultComponentResolver} + * Represents a resolver of components from a URI to be able to autoload them using some discovery mechanism. */ public interface ComponentResolver { diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java b/core/camel-api/src/main/java/org/apache/camel/spi/OptimisedComponentResolver.java similarity index 56% copy from core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java copy to core/camel-api/src/main/java/org/apache/camel/spi/OptimisedComponentResolver.java index 3d3f56ba529e..2e6504124199 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/OptimisedComponentResolver.java @@ -16,22 +16,19 @@ */ package org.apache.camel.spi; -import org.apache.camel.CamelContext; import org.apache.camel.Component; /** - * Represents a resolver of components from a URI to be able to auto-load them using some discovery mechanism like - * {@link org.apache.camel.impl.DefaultComponentResolver} + * A {@link Component} resolver that are used in EIPs with dynamic behavior such as toD, enrich and others. */ -public interface ComponentResolver { +public interface OptimisedComponentResolver { /** - * Attempts to resolve the component for the given URI + * Resolves the given component * - * @param name the component name to resolve - * @param context the context to load the component if it can be resolved - * @return the component which is added to the context or null if it cannot be resolved - * @throws Exception is thrown if the component could not be loaded + * @param uri the endpoint uri + * @return the component */ - Component resolveComponent(String name, CamelContext context) throws Exception; + Component resolveComponent(String uri); + } diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java index 10a97bdf0651..5477a2773ea1 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java @@ -141,6 +141,7 @@ import org.apache.camel.spi.ModelToYAMLDumper; import org.apache.camel.spi.ModelineFactory; import org.apache.camel.spi.NodeIdFactory; import org.apache.camel.spi.NormalizedEndpointUri; +import org.apache.camel.spi.OptimisedComponentResolver; import org.apache.camel.spi.PackageScanClassResolver; import org.apache.camel.spi.PackageScanResourceResolver; import org.apache.camel.spi.PeriodTaskResolver; @@ -363,6 +364,7 @@ public abstract class AbstractCamelContext extends BaseService camelContextExtension.addContextPlugin(FactoryFinderResolver.class, createFactoryFinderResolver()); camelContextExtension.addContextPlugin(PackageScanClassResolver.class, createPackageScanClassResolver()); camelContextExtension.addContextPlugin(PackageScanResourceResolver.class, createPackageScanResourceResolver()); + camelContextExtension.addContextPlugin(OptimisedComponentResolver.class, createOptimisedComponentResolver()); camelContextExtension.addContextPlugin(VariableRepositoryFactory.class, createVariableRepositoryFactory()); camelContextExtension.lazyAddContextPlugin(ModelineFactory.class, this::createModelineFactory); camelContextExtension.lazyAddContextPlugin(ModelJAXBContextFactory.class, this::createModelJAXBContextFactory); @@ -4488,6 +4490,8 @@ public abstract class AbstractCamelContext extends BaseService protected abstract TaskManagerRegistry createTaskManagerRegistry(); + protected abstract OptimisedComponentResolver createOptimisedComponentResolver(); + protected RestConfiguration createRestConfiguration() { // lookup a global which may have been on a container such spring-boot / CDI / etc. RestConfiguration conf diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultOptimisedComponentResolver.java similarity index 55% copy from core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java copy to core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultOptimisedComponentResolver.java index 3d3f56ba529e..fe9df3b86816 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/ComponentResolver.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultOptimisedComponentResolver.java @@ -14,24 +14,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.spi; +package org.apache.camel.impl.engine; import org.apache.camel.CamelContext; import org.apache.camel.Component; +import org.apache.camel.spi.OptimisedComponentResolver; +import org.apache.camel.support.ExchangeHelper; /** - * Represents a resolver of components from a URI to be able to auto-load them using some discovery mechanism like - * {@link org.apache.camel.impl.DefaultComponentResolver} + * Default {@link OptimisedComponentResolver}. */ -public interface ComponentResolver { +public class DefaultOptimisedComponentResolver implements OptimisedComponentResolver { - /** - * Attempts to resolve the component for the given URI - * - * @param name the component name to resolve - * @param context the context to load the component if it can be resolved - * @return the component which is added to the context or null if it cannot be resolved - * @throws Exception is thrown if the component could not be loaded - */ - Component resolveComponent(String name, CamelContext context) throws Exception; + private final CamelContext camelContext; + + public DefaultOptimisedComponentResolver(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + public Component resolveComponent(String uri) { + String scheme = ExchangeHelper.resolveScheme(uri); + if (scheme != null) { + return camelContext.getComponent(scheme); + } else { + return null; + } + } } diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java index 586db3d6ffa0..f25f6f7775b5 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java @@ -72,6 +72,7 @@ import org.apache.camel.spi.ModelToYAMLDumper; import org.apache.camel.spi.ModelineFactory; import org.apache.camel.spi.NodeIdFactory; import org.apache.camel.spi.NormalizedEndpointUri; +import org.apache.camel.spi.OptimisedComponentResolver; import org.apache.camel.spi.PackageScanClassResolver; import org.apache.camel.spi.PackageScanResourceResolver; import org.apache.camel.spi.PeriodTaskResolver; @@ -176,7 +177,7 @@ public class SimpleCamelContext extends AbstractCamelContext { @Override protected TypeConverter createTypeConverter() { return new DefaultTypeConverter( - getCamelContextReference(), PluginHelper.getPackageScanClassResolver(this), getInjector(), + getCamelContextReference(), PluginHelper.getPackageScanClassResolver(getCamelContextReference()), getInjector(), isLoadTypeConverters(), isTypeConverterStatisticsEnabled()); } @@ -588,7 +589,7 @@ public class SimpleCamelContext extends AbstractCamelContext { ResourceLoader.FACTORY, ResourceLoader.class); - return result.orElseGet(() -> new DefaultResourceLoader(this)); + return result.orElseGet(() -> new DefaultResourceLoader(getCamelContextReference())); } @Override @@ -763,12 +764,17 @@ public class SimpleCamelContext extends AbstractCamelContext { @Override protected BackOffTimerFactory createBackOffTimerFactory() { - return new DefaultBackOffTimerFactory(this); + return new DefaultBackOffTimerFactory(getCamelContextReference()); } @Override protected TaskManagerRegistry createTaskManagerRegistry() { - return new DefaultTaskManagerRegistry(this); + return new DefaultTaskManagerRegistry(getCamelContextReference()); + } + + @Override + protected OptimisedComponentResolver createOptimisedComponentResolver() { + return new DefaultOptimisedComponentResolver(getCamelContextReference()); } @Override diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/Enricher.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/Enricher.java index 33db45c6a7fa..0d69a6095b2e 100644 --- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/Enricher.java +++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/Enricher.java @@ -312,6 +312,7 @@ public class Enricher extends BaseProcessorSupport implements IdAware, RouteIdAw @Override protected void doInit() throws Exception { headersMapFactory = camelContext.getCamelContextExtension().getHeadersMapFactory(); + ServiceHelper.initService(processorExchangeFactory, aggregationStrategy, sendDynamicProcessor); } @Override diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/PollEnricher.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/PollEnricher.java index 3d720587fc55..cec2a0733974 100644 --- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/PollEnricher.java +++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/PollEnricher.java @@ -38,6 +38,7 @@ import org.apache.camel.spi.EndpointUtilizationStatistics; import org.apache.camel.spi.ExceptionHandler; import org.apache.camel.spi.HeadersMapFactory; import org.apache.camel.spi.IdAware; +import org.apache.camel.spi.OptimisedComponentResolver; import org.apache.camel.spi.PollDynamicAware; import org.apache.camel.spi.RouteIdAware; import org.apache.camel.support.BridgeExceptionHandlerToErrorHandler; @@ -596,8 +597,10 @@ public class PollEnricher extends BaseProcessorSupport implements IdAware, Route @Override protected void doStart() throws Exception { // ensure the component is started - if (autoStartupComponents && scheme != null) { - camelContext.getComponent(scheme); + if (autoStartupComponents && scheme != null && uri != null) { + OptimisedComponentResolver resolver + = camelContext.getCamelContextExtension().getContextPlugin(OptimisedComponentResolver.class); + resolver.resolveComponent(uri); } ServiceHelper.startService(consumerCache, aggregationStrategy, dynamicAware); diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java index 1b2bd97733d0..1285ecf4af8e 100644 --- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java +++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/SendDynamicProcessor.java @@ -34,6 +34,7 @@ import org.apache.camel.spi.EndpointUtilizationStatistics; import org.apache.camel.spi.HeadersMapFactory; import org.apache.camel.spi.IdAware; import org.apache.camel.spi.NormalizedEndpointUri; +import org.apache.camel.spi.OptimisedComponentResolver; import org.apache.camel.spi.ProducerCache; import org.apache.camel.spi.RouteIdAware; import org.apache.camel.spi.SendDynamicAware; @@ -375,8 +376,10 @@ public class SendDynamicProcessor extends BaseProcessorSupport implements IdAwar @Override protected void doStart() throws Exception { // ensure the component is started - if (autoStartupComponents && scheme != null) { - camelContext.getComponent(scheme); + if (autoStartupComponents && scheme != null && uri != null) { + OptimisedComponentResolver resolver + = camelContext.getCamelContextExtension().getContextPlugin(OptimisedComponentResolver.class); + resolver.resolveComponent(uri); } if (producerCache == null) { diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ExchangeHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/ExchangeHelper.java index c8fcc9e3f966..81c0f466b153 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/ExchangeHelper.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/ExchangeHelper.java @@ -918,6 +918,22 @@ public final class ExchangeHelper { return StringHelper.before(uri, ":"); } + /** + * Resolve the context-path from the given endpoint uri + * + * @param uri the endpoint uri + * @return the context path, or <tt>null</tt> if not possible to resolve + */ + public static String resolveContextPath(String uri) { + uri = StringHelper.before(uri, "?", uri); + if (uri.contains("://")) { + uri = StringHelper.after(uri, "://"); + } else { + uri = StringHelper.after(uri, ":"); + } + return uri; + } + /** * @see #getCharsetName(Exchange, boolean) */ diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java index 3e0b782c09cd..4ca3b0fd7c58 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java @@ -690,4 +690,51 @@ class ExportTest { } } + @ParameterizedTest + @MethodSource("runtimeProvider") + public void shouldExportToDWithCustomKamelet(RuntimeType rt) throws Exception { + LOG.info("shouldExportToDWithCustomKamelet {}", rt); + Export command = createCommand(rt, + new String[] { "src/test/resources/toDroute.yaml", "src/test/resources/cheese-sink.kamelet.yaml" }, + "--gav=examples:route:1.0.0", "--dir=" + workingDir, "--quiet"); + int exit = command.doCall(); + + Assertions.assertEquals(0, exit); + Model model = readMavenModel(); + Assertions.assertEquals("examples", model.getGroupId()); + Assertions.assertEquals("route", model.getArtifactId()); + Assertions.assertEquals("1.0.0", model.getVersion()); + + if (rt == RuntimeType.main) { + Assertions.assertTrue(containsDependency(model.getDependencies(), "org.apache.camel", "camel-log", null)); + Assertions.assertTrue(containsDependency(model.getDependencies(), "org.apache.camel", "camel-kamelet", null)); + Assertions + .assertFalse( + containsDependency(model.getDependencies(), "org.apache.camel.kamelets", "camel-kamelets", null)); + } else if (rt == RuntimeType.springBoot) { + Assertions.assertTrue( + containsDependency(model.getDependencies(), "org.apache.camel.springboot", "camel-log-starter", null)); + Assertions.assertTrue( + containsDependency(model.getDependencies(), "org.apache.camel.springboot", "camel-kamelet-starter", null)); + Assertions + .assertFalse( + containsDependency(model.getDependencies(), "org.apache.camel.kamelets", "camel-kamelets", null)); + } else if (rt == RuntimeType.quarkus) { + Assertions.assertTrue( + containsDependency(model.getDependencies(), "org.apache.camel.quarkus", "camel-quarkus-log", null)); + Assertions.assertTrue( + containsDependency(model.getDependencies(), "org.apache.camel.quarkus", "camel-quarkus-kamelet", null)); + Assertions + .assertFalse( + containsDependency(model.getDependencies(), "org.apache.camel.kamelets", "camel-kamelets", null)); + } + + File f = workingDir.toPath().resolve("src/main/resources/kamelets/cheese-sink.kamelet.yaml").toFile(); + Assertions.assertTrue(f.isFile()); + Assertions.assertTrue(f.exists()); + f = workingDir.toPath().resolve("src/main/resources/camel/toDroute.yaml").toFile(); + Assertions.assertTrue(f.isFile()); + Assertions.assertTrue(f.exists()); + } + } diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/resources/cheese-sink.kamelet.yaml b/dsl/camel-jbang/camel-jbang-core/src/test/resources/cheese-sink.kamelet.yaml new file mode 100644 index 000000000000..95d965509e68 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/test/resources/cheese-sink.kamelet.yaml @@ -0,0 +1,51 @@ +# +# 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. +# + +apiVersion: camel.apache.org/v1 +kind: Kamelet +metadata: + name: cheese-sink + labels: + camel.apache.org/kamelet.type: "sink" +spec: + definition: + title: "Log Sink" + description: A sink that logs all data that it receives, useful for debugging purposes. + required: + - showHeaders + properties: + showHeaders: + title: Show Headers + description: Show the headers received + type: boolean + showStreams: + title: Show Streams + description: Show the stream bodies (they may not be available in following steps) + type: boolean + default: false + dependencies: + - "camel:kamelet" + - "camel:log" + template: + from: + uri: "kamelet:source" + steps: + - to: + uri: "log:info" + parameters: + showHeaders: "{{?showHeaders}}" + showStreams: "{{?showStreams}}" \ No newline at end of file diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/resources/toDroute.yaml b/dsl/camel-jbang/camel-jbang-core/src/test/resources/toDroute.yaml new file mode 100644 index 000000000000..e0758cafe586 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/test/resources/toDroute.yaml @@ -0,0 +1,24 @@ +# +# 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: timer:tick + steps: + - setBody: + constant: Hello Camel !!! + - toD: + uri: kamelet:cheese-sink diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java index c067ea345a25..caff3eb0128d 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java @@ -65,6 +65,7 @@ import org.apache.camel.main.download.ExportTypeConverter; import org.apache.camel.main.download.JavaKnownImportsDownloader; import org.apache.camel.main.download.KameletAutowiredLifecycleStrategy; import org.apache.camel.main.download.KameletMainInjector; +import org.apache.camel.main.download.KameletOptimisedComponentResolver; import org.apache.camel.main.download.KnownDependenciesResolver; import org.apache.camel.main.download.KnownReposResolver; import org.apache.camel.main.download.MavenDependencyDownloader; @@ -96,6 +97,7 @@ import org.apache.camel.spi.FactoryFinder; import org.apache.camel.spi.FactoryFinderResolver; import org.apache.camel.spi.LanguageResolver; import org.apache.camel.spi.LifecycleStrategy; +import org.apache.camel.spi.OptimisedComponentResolver; import org.apache.camel.spi.PeriodTaskResolver; import org.apache.camel.spi.PeriodTaskScheduler; import org.apache.camel.spi.Registry; @@ -664,6 +666,8 @@ public class KameletMain extends MainCommandLineSupport { new DependencyDownloaderUriFactoryResolver(answer)); answer.getCamelContextExtension().addContextPlugin(ResourceLoader.class, new DependencyDownloaderResourceLoader(answer, sourceDir)); + answer.getCamelContextExtension().addContextPlugin(OptimisedComponentResolver.class, + new KameletOptimisedComponentResolver(answer)); if (stubPattern != null) { // need to replace autowire strategy with stub capable diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletOptimisedComponentResolver.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletOptimisedComponentResolver.java new file mode 100644 index 000000000000..7b2e6654530d --- /dev/null +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletOptimisedComponentResolver.java @@ -0,0 +1,61 @@ +/* + * 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.main.download; + +import org.apache.camel.CamelContext; +import org.apache.camel.Component; +import org.apache.camel.component.kamelet.KameletComponent; +import org.apache.camel.impl.engine.DefaultOptimisedComponentResolver; +import org.apache.camel.language.simple.SimpleLanguage; +import org.apache.camel.support.ExchangeHelper; +import org.apache.camel.support.RouteTemplateHelper; + +/** + * Dynamic EIPs that are using kamelets should preload kamelets so we can resolve dependencies and what components these + * kamelets are using as well. + */ +public class KameletOptimisedComponentResolver extends DefaultOptimisedComponentResolver { + + private final CamelContext camelContext; + + public KameletOptimisedComponentResolver(CamelContext camelContext) { + super(camelContext); + this.camelContext = camelContext; + } + + @Override + public Component resolveComponent(String uri) { + Component answer = super.resolveComponent(uri); + String scheme = ExchangeHelper.resolveScheme(uri); + // if a kamelet then we need to know the name of the kamelet spec in use + if ("kamelet".equals(scheme)) { + String name = ExchangeHelper.resolveContextPath(uri); + // must be a static name (so we can load the template and resolve nested dependencies) + if (!SimpleLanguage.hasSimpleFunction(name) && answer instanceof KameletComponent kc) { + // need to resolve dependencies from kamelet also + String loc = kc.getLocation(); + DependencyDownloaderKamelet listener = camelContext.hasService(DependencyDownloaderKamelet.class); + try { + RouteTemplateHelper.loadRouteTemplateFromLocation(camelContext, listener, name, loc); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + return answer; + } +}
