This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch jandex in repository https://gitbox.apache.org/repos/asf/camel.git
commit 6bc98b8a123b298b7dcc31c71ebceee7aec56d65 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Apr 10 12:09:58 2025 +0200 CAMEL-21944: camel-jbang - Classpath scan custom JARs for beans and processors with dependency injection annotations --- bom/camel-bom/pom.xml | 5 + catalog/camel-allcomponents/pom.xml | 5 + .../org/apache/camel/catalog/others.properties | 1 + .../org/apache/camel/catalog/others/jandex.json | 15 ++ .../bindy/util/AnnotationModuleLoaderTest.java | 2 +- components/camel-jandex/pom.xml | 70 ++++++++++ .../org/apache/camel/jandex-class-resolver | 2 + .../services/org/apache/camel/other.properties | 7 + .../src/generated/resources/jandex.json | 15 ++ components/camel-jandex/src/main/docs/jandex.adoc | 15 ++ .../jandex/JandexPackageScanClassResolver.java | 154 +++++++++++++++++++++ .../camel/component/jcr/JcrConverterTest.java | 2 +- .../component/salesforce/api/utils/JsonUtils.java | 2 +- .../org/apache/camel/spring/SpringTestSupport.java | 6 +- .../DefaultPackageResolverConfigureTest.java | 2 +- .../scan/DefaultPackageScanClassResolverTest.java | 2 +- .../camel/spring/scan/PackageScanFiltersTest.java | 10 +- .../camel/spring/config/PackageResolverTest.xml | 2 +- .../test/ExcludingPackageScanClassResolver.java | 6 +- .../camel/impl/engine/SimpleCamelContext.java | 3 + .../java/org/apache/camel/impl/scan/package.html | 27 ---- .../org/apache/camel/impl/DefaultCamelContext.java | 4 +- .../transformer/AnnotationTransformerLoader.java | 8 +- .../xml/AbstractCamelContextFactoryBeanTest.java | 2 +- .../org/apache/camel/converter/ConverterTest.java | 2 +- .../java/org/apache/camel/converter/JaxpTest.java | 2 +- .../apache/camel/converter/StringSourceTest.java | 2 +- .../apache/camel/model/ModelSanityCheckerTest.java | 2 +- .../scan/AnnotatedWithAnyPackageScanFilter.java | 7 +- .../scan/AnnotatedWithPackageScanFilter.java | 6 +- .../scan/AssignableToPackageScanFilter.java | 7 +- .../support/scan}/BasePackageScanResolver.java | 2 +- .../support}/scan/CompositePackageScanFilter.java | 2 +- .../scan}/DefaultPackageScanClassResolver.java | 6 +- .../scan}/DefaultPackageScanResourceResolver.java | 12 +- .../support}/scan/InvertingPackageScanFilter.java | 2 +- .../camel/support/scan/PackageScanJarResource.java | 67 +++++++++ .../scan}/WebSpherePackageScanClassResolver.java | 3 +- .../modules/others/examples/json/jandex.json | 1 + docs/components/modules/others/nav.adoc | 1 + docs/components/modules/others/pages/jandex.adoc | 1 + .../ROOT/pages/camel-4x-upgrade-guide-4_12.adoc | 12 ++ .../modules/ROOT/pages/camel-jbang.adoc | 6 + .../camel/dsl/jbang/core/commands/Export.java | 1 + .../dsl/jbang/core/commands/ExportBaseCommand.java | 7 +- .../apache/camel/dsl/jbang/core/commands/Run.java | 9 ++ .../core/commands/kubernetes/KubernetesExport.java | 2 + .../core/commands/kubernetes/KubernetesRun.java | 11 +- dsl/camel-kamelet-main/pom.xml | 4 + .../java/org/apache/camel/main/KameletMain.java | 18 ++- .../download/BasePackageScanDownloadListener.java | 146 ++++++++++++++++++- .../injection/AnnotationDependencyInjection.java | 11 ++ .../camel-main-known-dependencies.properties | 1 + parent/pom.xml | 5 + 54 files changed, 637 insertions(+), 88 deletions(-) diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml index 014102d6e44..7c731552fdc 100644 --- a/bom/camel-bom/pom.xml +++ b/bom/camel-bom/pom.xml @@ -1077,6 +1077,11 @@ <artifactId>camel-jacksonxml</artifactId> <version>4.12.0-SNAPSHOT</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jandex</artifactId> + <version>4.12.0-SNAPSHOT</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jasypt</artifactId> diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml index 82d6c18ccf3..e788e909b4f 100644 --- a/catalog/camel-allcomponents/pom.xml +++ b/catalog/camel-allcomponents/pom.xml @@ -946,6 +946,11 @@ <artifactId>camel-jacksonxml</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jandex</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jasypt</artifactId> diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties index 6b15779ac90..3c81f056b44 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties @@ -14,6 +14,7 @@ elytron endpointdsl headersmap health +jandex jasypt java-joor-dsl jfr diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/jandex.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/jandex.json new file mode 100644 index 00000000000..bb305950e1b --- /dev/null +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/jandex.json @@ -0,0 +1,15 @@ +{ + "other": { + "kind": "other", + "name": "jandex", + "title": "Jandex", + "description": "Custom class and resource loader using jandex.idx", + "deprecated": false, + "firstVersion": "4.12.0", + "label": "core", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-jandex", + "version": "4.12.0-SNAPSHOT" + } +} diff --git a/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/util/AnnotationModuleLoaderTest.java b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/util/AnnotationModuleLoaderTest.java index 14927251d9c..a3c8d7fc9d9 100644 --- a/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/util/AnnotationModuleLoaderTest.java +++ b/components/camel-bindy/src/test/java/org/apache/camel/dataformat/bindy/util/AnnotationModuleLoaderTest.java @@ -21,7 +21,7 @@ import java.util.Set; import org.apache.camel.dataformat.bindy.model.complex.twoclassesandonelink.Client; import org.apache.camel.dataformat.bindy.model.complex.twoclassesandonelink.Order; import org.apache.camel.dataformat.bindy.model.complex.twoclassesandonelink.Security; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/components/camel-jandex/pom.xml b/components/camel-jandex/pom.xml new file mode 100644 index 00000000000..9ff10c47080 --- /dev/null +++ b/components/camel-jandex/pom.xml @@ -0,0 +1,70 @@ +<?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>components</artifactId> + <version>4.12.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-jandex</artifactId> + <packaging>jar</packaging> + <name>Camel :: Jandex</name> + <description>Custom class and resource loader using jandex.idx</description> + + <properties> + <firstVersion>4.12.0</firstVersion> + <label>core</label> + </properties> + + <dependencies> + + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-support</artifactId> + </dependency> + + <dependency> + <groupId>io.smallrye</groupId> + <artifactId>jandex</artifactId> + <version>${jandex-version}</version> + </dependency> + + <!-- testing --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test-junit5</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-mock</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + +</project> diff --git a/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/jandex-class-resolver b/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/jandex-class-resolver new file mode 100644 index 00000000000..140c6c47810 --- /dev/null +++ b/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/jandex-class-resolver @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.jandex.JandexPackageScanClassResolver diff --git a/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/other.properties new file mode 100644 index 00000000000..63affc04782 --- /dev/null +++ b/components/camel-jandex/src/generated/resources/META-INF/services/org/apache/camel/other.properties @@ -0,0 +1,7 @@ +# Generated by camel build tools - do NOT edit this file! +name=jandex +groupId=org.apache.camel +artifactId=camel-jandex +version=4.12.0-SNAPSHOT +projectName=Camel :: Jandex +projectDescription=Custom class and resource loader using jandex.idx diff --git a/components/camel-jandex/src/generated/resources/jandex.json b/components/camel-jandex/src/generated/resources/jandex.json new file mode 100644 index 00000000000..bb305950e1b --- /dev/null +++ b/components/camel-jandex/src/generated/resources/jandex.json @@ -0,0 +1,15 @@ +{ + "other": { + "kind": "other", + "name": "jandex", + "title": "Jandex", + "description": "Custom class and resource loader using jandex.idx", + "deprecated": false, + "firstVersion": "4.12.0", + "label": "core", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-jandex", + "version": "4.12.0-SNAPSHOT" + } +} diff --git a/components/camel-jandex/src/main/docs/jandex.adoc b/components/camel-jandex/src/main/docs/jandex.adoc new file mode 100644 index 00000000000..daead9510b9 --- /dev/null +++ b/components/camel-jandex/src/main/docs/jandex.adoc @@ -0,0 +1,15 @@ += Jandex Component +:doctitle: Jandex +:shortname: jandex +:artifactid: camel-jandex +:description: Custom class and resource loader using jandex.idx +:since: 4.12 +:supportlevel: Preview +:tabs-sync-option: + +*Since Camel {since}* + +The Jandex component is class and resource loader that uses the META-INF/jandex.idx index file +for fast classpath scanning. + +This allows much quicker classpath scanning of JARs that has been indexed. \ No newline at end of file diff --git a/components/camel-jandex/src/main/java/org/apache/camel/jandex/JandexPackageScanClassResolver.java b/components/camel-jandex/src/main/java/org/apache/camel/jandex/JandexPackageScanClassResolver.java new file mode 100644 index 00000000000..00426457c64 --- /dev/null +++ b/components/camel-jandex/src/main/java/org/apache/camel/jandex/JandexPackageScanClassResolver.java @@ -0,0 +1,154 @@ +/* + * 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.jandex; + +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.camel.spi.PackageScanFilter; +import org.apache.camel.spi.PackageScanResourceResolver; +import org.apache.camel.spi.Resource; +import org.apache.camel.spi.annotations.JdkService; +import org.apache.camel.support.PluginHelper; +import org.apache.camel.support.scan.AnnotatedWithAnyPackageScanFilter; +import org.apache.camel.support.scan.AnnotatedWithPackageScanFilter; +import org.apache.camel.support.scan.AssignableToPackageScanFilter; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.ClassInfo; +import org.jboss.jandex.Index; +import org.jboss.jandex.IndexReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@JdkService("jandex-class-resolver") +public class JandexPackageScanClassResolver extends DefaultPackageScanClassResolver { + + private static final Logger LOG = LoggerFactory.getLogger(JandexPackageScanClassResolver.class); + + private static final String INDEX = "classpath:META-INF/jandex.*"; + private final List<Index> indexes = new ArrayList<>(); + + @Override + protected void doStart() throws Exception { + super.doStart(); + + PackageScanResourceResolver resolver = PluginHelper.getPackageScanResourceResolver(getCamelContext()); + resolver.addClassLoader(getCamelContext().getApplicationContextClassLoader()); + resolver.start(); + + var list = resolver.findResources(INDEX); + + for (Resource res : list) { + if (res.getLocation().endsWith("jandex.idx")) { + try (InputStream is = res.getInputStream()) { + if (is != null) { + LOG.debug("Reading jandex.idx from: {}", res.getLocation()); + Index index = new IndexReader(is).read(); + indexes.add(index); + } + } + } + } + } + + @Override + protected void doStop() throws Exception { + super.doStop(); + indexes.clear(); + } + + @Override + protected void find(PackageScanFilter test, String packageName, ClassLoader loader, Set<Class<?>> classes) { + if (test instanceof AnnotatedWithPackageScanFilter ann) { + findByAnnotation(ann.getAnnotation(), classes); + } + if (test instanceof AnnotatedWithAnyPackageScanFilter ann) { + for (var c : ann.getAnnotations()) { + findByAnnotation(c, classes); + } + } + if (test instanceof AssignableToPackageScanFilter ann) { + for (var c : ann.getParents()) { + findBySubClass(c, classes); + } + } + } + + private void findByAnnotation(Class<? extends Annotation> c, Set<Class<?>> classes) { + for (Index index : indexes) { + for (var ai : index.getAnnotations(c)) { + var at = ai.target(); + if (at.kind() == AnnotationTarget.Kind.CLASS + && at.asClass().nestingType() == ClassInfo.NestingType.TOP_LEVEL) { + if (!at.asClass().isAbstract()) { + String currentClass = at.asClass().name().toString(); + for (ClassLoader cl : getClassLoaders()) { + try { + Class<?> clazz = cl.loadClass(currentClass); + classes.add(clazz); + break; + } catch (ClassNotFoundException e) { + // ignore + } + } + } + } + } + } + } + + private void findBySubClass(Class<?> c, Set<Class<?>> classes) { + for (Index index : indexes) { + if (c.isInterface()) { + for (var ai : index.getAllKnownImplementations(c)) { + if (!ai.asClass().isAbstract()) { + String currentClass = ai.asClass().name().toString(); + for (ClassLoader cl : getClassLoaders()) { + try { + Class<?> clazz = cl.loadClass(currentClass); + classes.add(clazz); + break; + } catch (ClassNotFoundException e) { + // ignore + } + } + } + } + } else { + for (var ai : index.getAllKnownSubclasses(c)) { + if (!ai.isAbstract()) { + String currentClass = ai.asClass().name().toString(); + for (ClassLoader cl : getClassLoaders()) { + try { + Class<?> clazz = cl.loadClass(currentClass); + classes.add(clazz); + break; + } catch (ClassNotFoundException e) { + // ignore + } + } + } + } + } + } + } + +} diff --git a/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java b/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java index 5a4fde0243b..28ea74fdea8 100644 --- a/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java +++ b/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java @@ -23,9 +23,9 @@ import javax.jcr.Value; import org.apache.camel.TypeConverter; import org.apache.camel.impl.converter.DefaultTypeConverter; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; import org.apache.camel.spi.Injector; import org.apache.camel.support.ObjectHelper; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; import org.apache.camel.support.service.ServiceHelper; import org.apache.jackrabbit.value.BinaryValue; import org.apache.jackrabbit.value.BooleanValue; diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/utils/JsonUtils.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/utils/JsonUtils.java index 3c7a134372b..e28353da48d 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/utils/JsonUtils.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/utils/JsonUtils.java @@ -60,7 +60,7 @@ import org.apache.camel.component.salesforce.api.dto.PickListValue; import org.apache.camel.component.salesforce.api.dto.SObject; import org.apache.camel.component.salesforce.api.dto.SObjectDescription; import org.apache.camel.component.salesforce.api.dto.SObjectField; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; import static java.util.stream.Collectors.joining; diff --git a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringTestSupport.java b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringTestSupport.java index 0f1617d2dc9..af2e4e7f763 100644 --- a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringTestSupport.java +++ b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/SpringTestSupport.java @@ -30,9 +30,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.ContextTestSupport; import org.apache.camel.component.seda.SedaComponent; import org.apache.camel.impl.DefaultCamelContext; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; -import org.apache.camel.impl.scan.AssignableToPackageScanFilter; -import org.apache.camel.impl.scan.InvertingPackageScanFilter; +import org.apache.camel.support.scan.AssignableToPackageScanFilter; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; +import org.apache.camel.support.scan.InvertingPackageScanFilter; import org.apache.camel.util.IOHelper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; diff --git a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/config/DefaultPackageResolverConfigureTest.java b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/config/DefaultPackageResolverConfigureTest.java index 52e93b35391..5a36dc85511 100644 --- a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/config/DefaultPackageResolverConfigureTest.java +++ b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/config/DefaultPackageResolverConfigureTest.java @@ -16,9 +16,9 @@ */ package org.apache.camel.spring.config; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; import org.apache.camel.spring.SpringTestSupport; import org.apache.camel.support.PluginHelper; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; import org.junit.jupiter.api.Test; import org.springframework.context.support.AbstractXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; diff --git a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/DefaultPackageScanClassResolverTest.java b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/DefaultPackageScanClassResolverTest.java index f80e2655f8b..c5e1e685dd4 100644 --- a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/DefaultPackageScanClassResolverTest.java +++ b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/DefaultPackageScanClassResolverTest.java @@ -22,10 +22,10 @@ import java.net.URLClassLoader; import java.util.HashSet; import java.util.Set; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; import org.apache.camel.spring.scan.a.ScanTargetOne; import org.apache.camel.spring.scan.b.ScanTargetTwo; import org.apache.camel.spring.scan.c.ScanTargetThree; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/PackageScanFiltersTest.java b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/PackageScanFiltersTest.java index b9ef66f1aec..6fb8ba61f5c 100644 --- a/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/PackageScanFiltersTest.java +++ b/components/camel-spring-parent/camel-spring-xml/src/test/java/org/apache/camel/spring/scan/PackageScanFiltersTest.java @@ -20,15 +20,15 @@ import java.lang.annotation.Annotation; import java.util.LinkedHashSet; import java.util.Set; -import org.apache.camel.impl.scan.AnnotatedWithAnyPackageScanFilter; -import org.apache.camel.impl.scan.AnnotatedWithPackageScanFilter; -import org.apache.camel.impl.scan.AssignableToPackageScanFilter; -import org.apache.camel.impl.scan.CompositePackageScanFilter; -import org.apache.camel.impl.scan.InvertingPackageScanFilter; import org.apache.camel.spi.PackageScanFilter; import org.apache.camel.spring.scan.a.ScanTargetOne; import org.apache.camel.spring.scan.b.ScanTargetTwo; import org.apache.camel.spring.scan.c.ScanTargetThree; +import org.apache.camel.support.scan.AnnotatedWithAnyPackageScanFilter; +import org.apache.camel.support.scan.AnnotatedWithPackageScanFilter; +import org.apache.camel.support.scan.AssignableToPackageScanFilter; +import org.apache.camel.support.scan.CompositePackageScanFilter; +import org.apache.camel.support.scan.InvertingPackageScanFilter; import org.apache.camel.util.CollectionHelper; import org.junit.jupiter.api.Test; diff --git a/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/PackageResolverTest.xml b/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/PackageResolverTest.xml index 146b1587ff5..95b25d52e2f 100644 --- a/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/PackageResolverTest.xml +++ b/components/camel-spring-parent/camel-spring-xml/src/test/resources/org/apache/camel/spring/config/PackageResolverTest.xml @@ -24,7 +24,7 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> - <bean id="myPackageResolver" class="org.apache.camel.impl.engine.DefaultPackageScanClassResolver" > + <bean id="myPackageResolver" class="org.apache.camel.support.scan.DefaultPackageScanClassResolver" > <property name="AcceptableSchemes" value="test:;test2:"/> </bean> diff --git a/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/ExcludingPackageScanClassResolver.java b/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/ExcludingPackageScanClassResolver.java index 4bcfd9f5a93..1151e429214 100644 --- a/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/ExcludingPackageScanClassResolver.java +++ b/components/camel-test/camel-test-junit5/src/main/java/org/apache/camel/test/ExcludingPackageScanClassResolver.java @@ -19,9 +19,9 @@ package org.apache.camel.test; import java.util.Collections; import java.util.Set; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; -import org.apache.camel.impl.scan.AssignableToPackageScanFilter; -import org.apache.camel.impl.scan.InvertingPackageScanFilter; +import org.apache.camel.support.scan.AssignableToPackageScanFilter; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; +import org.apache.camel.support.scan.InvertingPackageScanFilter; public class ExcludingPackageScanClassResolver extends DefaultPackageScanClassResolver { 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 8cdc1ecf083..8710b8d4c50 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 @@ -99,6 +99,9 @@ import org.apache.camel.support.DefaultRegistry; import org.apache.camel.support.DefaultUuidGenerator; import org.apache.camel.support.PluginHelper; import org.apache.camel.support.ResolverHelper; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; +import org.apache.camel.support.scan.DefaultPackageScanResourceResolver; +import org.apache.camel.support.scan.WebSpherePackageScanClassResolver; import org.apache.camel.support.startup.DefaultStartupConditionStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/scan/package.html b/core/camel-base/src/main/java/org/apache/camel/impl/scan/package.html deleted file mode 100644 index 4b17e11ac2c..00000000000 --- a/core/camel-base/src/main/java/org/apache/camel/impl/scan/package.html +++ /dev/null @@ -1,27 +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. - ---> -<html> -<head> -</head> -<body> - -Package scan classes. - -</body> -</html> diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java index 87675091e80..064eabac97c 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java @@ -39,8 +39,6 @@ import org.apache.camel.api.management.JmxSystemPropertyKeys; import org.apache.camel.impl.engine.DefaultExecutorServiceManager; import org.apache.camel.impl.engine.RouteService; import org.apache.camel.impl.engine.SimpleCamelContext; -import org.apache.camel.impl.scan.AssignableToPackageScanFilter; -import org.apache.camel.impl.scan.InvertingPackageScanFilter; import org.apache.camel.model.BeanFactoryDefinition; import org.apache.camel.model.DataFormatDefinition; import org.apache.camel.model.FaultToleranceConfigurationDefinition; @@ -81,6 +79,8 @@ import org.apache.camel.support.DefaultRegistry; import org.apache.camel.support.LocalBeanRegistry; import org.apache.camel.support.ResolverHelper; import org.apache.camel.support.SimpleUuidGenerator; +import org.apache.camel.support.scan.AssignableToPackageScanFilter; +import org.apache.camel.support.scan.InvertingPackageScanFilter; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.OrderedLocationProperties; import org.apache.camel.util.StopWatch; diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/transformer/AnnotationTransformerLoader.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/transformer/AnnotationTransformerLoader.java index 7201b1f55a0..b668c370d3d 100644 --- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/transformer/AnnotationTransformerLoader.java +++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/transformer/AnnotationTransformerLoader.java @@ -28,10 +28,8 @@ import java.util.Set; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; -import org.apache.camel.ExtendedCamelContext; import org.apache.camel.Message; import org.apache.camel.TypeConverterLoaderException; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; import org.apache.camel.spi.DataType; import org.apache.camel.spi.DataTypeTransformer; import org.apache.camel.spi.PackageScanClassResolver; @@ -69,11 +67,7 @@ public class AnnotationTransformerLoader extends Transformer implements Transfor ObjectHelper.notNull(camelContext, "camelContext"); if (resolver == null) { - if (camelContext instanceof ExtendedCamelContext) { - resolver = PluginHelper.getPackageScanClassResolver(camelContext); - } else { - resolver = new DefaultPackageScanClassResolver(); - } + resolver = PluginHelper.getPackageScanClassResolver(camelContext); } Set<String> packages = new HashSet<>(); diff --git a/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java b/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java index c8ac3be4565..9cbe70da6db 100644 --- a/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java +++ b/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java @@ -29,7 +29,6 @@ import org.apache.camel.Service; import org.apache.camel.TypeConverter; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.impl.converter.DefaultTypeConverter; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; import org.apache.camel.model.ModelCamelContext; import org.apache.camel.spi.CamelBeanPostProcessor; import org.apache.camel.spi.ExecutorServiceManager; @@ -38,6 +37,7 @@ import org.apache.camel.spi.Injector; import org.apache.camel.spi.ManagementNameStrategy; import org.apache.camel.spi.RuntimeEndpointRegistry; import org.apache.camel.support.ObjectHelper; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; diff --git a/core/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java b/core/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java index 0c890ed5899..9443555c0ff 100644 --- a/core/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/converter/ConverterTest.java @@ -34,10 +34,10 @@ import org.apache.camel.TypeConversionException; import org.apache.camel.TypeConverter; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.impl.converter.DefaultTypeConverter; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; import org.apache.camel.spi.BeanIntrospection; import org.apache.camel.support.DefaultExchange; import org.apache.camel.support.PluginHelper; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; import org.apache.camel.support.service.ServiceHelper; import org.apache.camel.util.ReflectionInjector; import org.junit.jupiter.api.BeforeEach; diff --git a/core/camel-core/src/test/java/org/apache/camel/converter/JaxpTest.java b/core/camel-core/src/test/java/org/apache/camel/converter/JaxpTest.java index 8d93590bb23..99556b25e67 100644 --- a/core/camel-core/src/test/java/org/apache/camel/converter/JaxpTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/converter/JaxpTest.java @@ -28,7 +28,7 @@ import org.w3c.dom.Element; import org.apache.camel.TypeConverter; import org.apache.camel.impl.converter.DefaultTypeConverter; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; import org.apache.camel.support.service.ServiceHelper; import org.apache.camel.util.ReflectionInjector; import org.junit.jupiter.api.BeforeEach; diff --git a/core/camel-core/src/test/java/org/apache/camel/converter/StringSourceTest.java b/core/camel-core/src/test/java/org/apache/camel/converter/StringSourceTest.java index f10c71a8ce9..14610d01ee6 100644 --- a/core/camel-core/src/test/java/org/apache/camel/converter/StringSourceTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/converter/StringSourceTest.java @@ -23,7 +23,7 @@ import java.io.ObjectOutputStream; import org.apache.camel.TypeConverter; import org.apache.camel.impl.converter.DefaultTypeConverter; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; import org.apache.camel.support.service.ServiceHelper; import org.apache.camel.util.ReflectionInjector; import org.apache.camel.util.xml.StringSource; diff --git a/core/camel-core/src/test/java/org/apache/camel/model/ModelSanityCheckerTest.java b/core/camel-core/src/test/java/org/apache/camel/model/ModelSanityCheckerTest.java index 3cda42131a5..0837960c160 100644 --- a/core/camel-core/src/test/java/org/apache/camel/model/ModelSanityCheckerTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/model/ModelSanityCheckerTest.java @@ -27,9 +27,9 @@ import jakarta.xml.bind.annotation.XmlElementRef; import org.apache.camel.CamelContext; import org.apache.camel.impl.DefaultCamelContext; -import org.apache.camel.impl.engine.DefaultPackageScanClassResolver; import org.apache.camel.spi.BeanIntrospection; import org.apache.camel.support.PluginHelper; +import org.apache.camel.support.scan.DefaultPackageScanClassResolver; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java b/core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithAnyPackageScanFilter.java similarity index 93% rename from core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java rename to core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithAnyPackageScanFilter.java index 8c3b7be4498..0f66b8b519d 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithAnyPackageScanFilter.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithAnyPackageScanFilter.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.scan; +package org.apache.camel.support.scan; import java.lang.annotation.Annotation; import java.util.Set; @@ -26,6 +26,7 @@ import org.apache.camel.util.ObjectHelper; * Package scan filter for testing if a given class is annotated with any of the annotations. */ public class AnnotatedWithAnyPackageScanFilter implements PackageScanFilter { + private final Set<Class<? extends Annotation>> annotations; private final boolean checkMetaAnnotations; @@ -51,6 +52,10 @@ public class AnnotatedWithAnyPackageScanFilter implements PackageScanFilter { return false; } + public Set<Class<? extends Annotation>> getAnnotations() { + return annotations; + } + @Override public String toString() { return "annotated with any @[" + annotations + "]"; diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java b/core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithPackageScanFilter.java similarity index 93% rename from core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java rename to core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithPackageScanFilter.java index f30b67d466a..b4d51ee5a37 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AnnotatedWithPackageScanFilter.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/scan/AnnotatedWithPackageScanFilter.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.scan; +package org.apache.camel.support.scan; import java.lang.annotation.Annotation; @@ -43,6 +43,10 @@ public class AnnotatedWithPackageScanFilter implements PackageScanFilter { return type != null && ObjectHelper.hasAnnotation(type, annotation, checkMetaAnnotations); } + public Class<? extends Annotation> getAnnotation() { + return annotation; + } + @Override public String toString() { return "annotated with @" + annotation.getSimpleName(); diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java b/core/camel-support/src/main/java/org/apache/camel/support/scan/AssignableToPackageScanFilter.java similarity index 95% rename from core/camel-base/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java rename to core/camel-support/src/main/java/org/apache/camel/support/scan/AssignableToPackageScanFilter.java index 2c527e892a1..4e0a2609cb4 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/scan/AssignableToPackageScanFilter.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/scan/AssignableToPackageScanFilter.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.scan; +package org.apache.camel.support.scan; import java.lang.reflect.Modifier; import java.util.HashSet; @@ -26,6 +26,7 @@ import org.apache.camel.spi.PackageScanFilter; * Package scan filter for testing if a given class is assignable to another class. */ public class AssignableToPackageScanFilter implements PackageScanFilter { + private final Set<Class<?>> parents = new HashSet<>(); private boolean includeAbstract; @@ -40,6 +41,10 @@ public class AssignableToPackageScanFilter implements PackageScanFilter { this.parents.addAll(parents); } + public Set<Class<?>> getParents() { + return parents; + } + public void addParentType(Class<?> parentType) { parents.add(parentType); } diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/BasePackageScanResolver.java b/core/camel-support/src/main/java/org/apache/camel/support/scan/BasePackageScanResolver.java similarity index 99% rename from core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/BasePackageScanResolver.java rename to core/camel-support/src/main/java/org/apache/camel/support/scan/BasePackageScanResolver.java index b8de017669c..538914ba8a3 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/BasePackageScanResolver.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/scan/BasePackageScanResolver.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.engine; +package org.apache.camel.support.scan; import java.io.IOException; import java.net.URI; diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java b/core/camel-support/src/main/java/org/apache/camel/support/scan/CompositePackageScanFilter.java similarity index 97% rename from core/camel-base/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java rename to core/camel-support/src/main/java/org/apache/camel/support/scan/CompositePackageScanFilter.java index 8ba1c4c0bca..0a17184b6be 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/scan/CompositePackageScanFilter.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/scan/CompositePackageScanFilter.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.scan; +package org.apache.camel.support.scan; import java.util.LinkedHashSet; import java.util.Set; diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanClassResolver.java b/core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanClassResolver.java similarity index 98% rename from core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanClassResolver.java rename to core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanClassResolver.java index 3e1dff0f322..7be2ef5165d 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanClassResolver.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanClassResolver.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.engine; +package org.apache.camel.support.scan; import java.io.File; import java.io.FileInputStream; @@ -35,10 +35,6 @@ import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import org.apache.camel.NonManagedService; -import org.apache.camel.impl.scan.AnnotatedWithAnyPackageScanFilter; -import org.apache.camel.impl.scan.AnnotatedWithPackageScanFilter; -import org.apache.camel.impl.scan.AssignableToPackageScanFilter; -import org.apache.camel.impl.scan.CompositePackageScanFilter; import org.apache.camel.spi.PackageScanClassResolver; import org.apache.camel.spi.PackageScanFilter; import org.apache.camel.support.LRUCacheFactory; diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java b/core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanResourceResolver.java similarity index 97% rename from core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java rename to core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanResourceResolver.java index 563a6c09b9d..4c177251ae7 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultPackageScanResourceResolver.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/scan/DefaultPackageScanResourceResolver.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.engine; +package org.apache.camel.support.scan; import java.io.File; import java.io.FileInputStream; @@ -174,8 +174,7 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver LOG.trace("Loading from jar using file: {}", file); stream = new FileInputStream(file); } - - loadImplementationsInJar(packageName, subPattern, stream, urlPath, resources); + loadImplementationsInJar(url, packageName, subPattern, stream, urlPath, resources); } } catch (IOException e) { // use debug logging to avoid being to noisy in logs @@ -195,6 +194,7 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver * @param resources the list to add loaded resources */ protected void loadImplementationsInJar( + URL url, String packageName, String subPattern, InputStream stream, @@ -207,9 +207,8 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver boolean match = PATH_MATCHER.match(subPattern, shortName); LOG.debug("Found resource: {} matching pattern: {} -> {}", shortName, subPattern, match); if (match) { - final ResourceLoader loader = PluginHelper.getResourceLoader(getCamelContext()); - - resources.add(loader.resolveResource(name)); + Resource resource = new PackageScanJarResource("jar", url, name); + resources.add(resource); } } } @@ -281,7 +280,6 @@ public class DefaultPackageScanResourceResolver extends BasePackageScanResolver LOG.debug("Found resource: {} matching pattern: {} -> {}", name, subPattern, match); if (match) { final ResourceLoader loader = PluginHelper.getResourceLoader(getCamelContext()); - resources.add(loader.resolveResource("file:" + file.getPath())); } } diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java b/core/camel-support/src/main/java/org/apache/camel/support/scan/InvertingPackageScanFilter.java similarity index 97% rename from core/camel-base/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java rename to core/camel-support/src/main/java/org/apache/camel/support/scan/InvertingPackageScanFilter.java index b072f1bf8db..6b5b2460cfe 100644 --- a/core/camel-base/src/main/java/org/apache/camel/impl/scan/InvertingPackageScanFilter.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/scan/InvertingPackageScanFilter.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.scan; +package org.apache.camel.support.scan; import org.apache.camel.spi.PackageScanFilter; diff --git a/core/camel-support/src/main/java/org/apache/camel/support/scan/PackageScanJarResource.java b/core/camel-support/src/main/java/org/apache/camel/support/scan/PackageScanJarResource.java new file mode 100644 index 00000000000..3ef8693a4bb --- /dev/null +++ b/core/camel-support/src/main/java/org/apache/camel/support/scan/PackageScanJarResource.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.support.scan; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; + +import org.apache.camel.support.ResourceSupport; +import org.apache.camel.util.FileUtil; +import org.apache.camel.util.StringHelper; + +public class PackageScanJarResource extends ResourceSupport { + + private final URL url; + private final URLClassLoader uc; + + public PackageScanJarResource(String scheme, URL url, String location) { + super(scheme, url.getFile() + FileUtil.stripPath(location)); + this.url = url; + this.uc = new URLClassLoader(new URL[] { url }); + } + + @Override + public URL getURL() throws MalformedURLException { + return url; + } + + @Override + public boolean exists() { + return true; + } + + @Override + public URI getURI() { + try { + return url.toURI(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + @Override + public InputStream getInputStream() throws IOException { + String loc = StringHelper.after(getLocation(), "!"); + return uc.getResourceAsStream(loc); + } + +} diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/WebSpherePackageScanClassResolver.java b/core/camel-support/src/main/java/org/apache/camel/support/scan/WebSpherePackageScanClassResolver.java similarity index 98% rename from core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/WebSpherePackageScanClassResolver.java rename to core/camel-support/src/main/java/org/apache/camel/support/scan/WebSpherePackageScanClassResolver.java index 250f593414b..3b26c38a42a 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/WebSpherePackageScanClassResolver.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/scan/WebSpherePackageScanClassResolver.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.impl.engine; +package org.apache.camel.support.scan; import java.io.IOException; import java.net.URL; @@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory; /** * WebSphere specific resolver to handle loading annotated resources in JAR files. */ +@Deprecated public class WebSpherePackageScanClassResolver extends DefaultPackageScanClassResolver { private static final Logger LOG = LoggerFactory.getLogger(WebSpherePackageScanClassResolver.class); diff --git a/docs/components/modules/others/examples/json/jandex.json b/docs/components/modules/others/examples/json/jandex.json new file mode 120000 index 00000000000..074f26f1f8a --- /dev/null +++ b/docs/components/modules/others/examples/json/jandex.json @@ -0,0 +1 @@ +../../../../../../components/camel-jandex/src/generated/resources/jandex.json \ No newline at end of file diff --git a/docs/components/modules/others/nav.adoc b/docs/components/modules/others/nav.adoc index 9bac32ee593..f1c13d88801 100644 --- a/docs/components/modules/others/nav.adoc +++ b/docs/components/modules/others/nav.adoc @@ -20,6 +20,7 @@ *** xref:yaml-dsl.adoc[YAML DSL] ** xref:elytron.adoc[Elytron] ** xref:headersmap.adoc[Headersmap] +** xref:jandex.adoc[Jandex] ** xref:jasypt.adoc[Jasypt] ** xref:jfr.adoc[JFR] ** xref:jta.adoc[JTA] diff --git a/docs/components/modules/others/pages/jandex.adoc b/docs/components/modules/others/pages/jandex.adoc new file mode 120000 index 00000000000..aa13a8a514e --- /dev/null +++ b/docs/components/modules/others/pages/jandex.adoc @@ -0,0 +1 @@ +../../../../../components/camel-jandex/src/main/docs/jandex.adoc \ No newline at end of file diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_12.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_12.adoc index 0db3d8f98cc..402ae9bac05 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_12.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_12.adoc @@ -6,6 +6,18 @@ from both 4.0 to 4.1 and 4.1 to 4.2. == Upgrading Camel 4.11 to 4.12 +=== camel-core + +The package scan classes has moved from `camel-base-engine` to `camel-support` JAR and moved to a new package: + +- `org.apache.camel.impl.engine.DefaultPackageScanClassResolver` is moved to `org.apache.camel.support.scan.DefaultPackageScanClassResolver` +- `org.apache.camel.impl.engine.DefaultPackageScanResourceResolver` is moved to `org.apache.camel.support.scan.DefaultPackageScanResourceResolver` +- `org.apache.camel.impl.scan.AnnotatedWithAnyPackageScanFilter` is moved to `org.apache.camel.support.scan.AnnotatedWithAnyPackageScanFilter` +- `org.apache.camel.impl.scan.AnnotatedWithPackageScanFilter` is moved to `org.apache.camel.support.scan.AnnotatedWithPackageScanFilter` +- `org.apache.camel.impl.scan.AssignableToPackageScanFilter` is moved to `org.apache.camel.support.scan.AssignableToPackageScanFilter` +- `org.apache.camel.impl.scan.CompositePackageScanFilter` is moved to `org.apache.camel.support.scan.CompositePackageScanFilter` +- `org.apache.camel.impl.scan.InvertingPackageScanFilter` is moved to `org.apache.camel.support.scan.InvertingPackageScanFilter` + === camel-as2 Add options allowing the addition of an `Authorization` header for Basic or Bearer authentication to client and diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc index b58521539b6..a8403bf4b8c 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc @@ -3853,6 +3853,12 @@ The follow options related to _exporting_, can be configured in `application.pro |`camel.jbang.mavenApacheSnapshotEnabled` |Whether downloading JARs from ASF Maven Snapshot repository is enabled +|`camel.jbang.download` +Whether to allow automatic downloading JAR dependencies (over the internet) + +|`camel.jbang.packageScanJars` +Whether to automatic package scan JARs for custom Spring or Quarkus beans making them available for Camel JBang + |`camel.jbang.exportDir` |Directory where the project will be exported diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java index c7a8578886a..7b70debeff5 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java @@ -149,6 +149,7 @@ public class Export extends ExportBaseCommand { cmd.cleanExportDir = this.cleanExportDir; cmd.fresh = this.fresh; cmd.download = this.download; + cmd.packageScanJars = this.packageScanJars; cmd.javaVersion = this.javaVersion; cmd.camelVersion = this.camelVersion; cmd.kameletsVersion = this.kameletsVersion; diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java index 3d3fcdc5b7d..597dc4470b6 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java @@ -221,11 +221,15 @@ public abstract class ExportBaseCommand extends CamelCommand { description = "Whether to allow automatic downloading JAR dependencies (over the internet)") protected boolean download = true; + @CommandLine.Option(names = { "--package-scan-jars" }, defaultValue = "false", + description = "Whether to automatic package scan JARs for custom Spring or Quarkus beans making them available for Camel JBang") + protected boolean packageScanJars; + @CommandLine.Option(names = { "--build-property" }, description = "Maven/Gradle build properties, ex. --build-property=prop1=foo") protected List<String> buildProperties = new ArrayList<>(); - @CommandLine.Option(names = { "--property" }, + @CommandLine.Option(names = { "--prop", "--property" }, description = "Camel application properties, ex. --property=prop1=foo") protected String[] applicationProperties; @@ -334,6 +338,7 @@ public abstract class ExportBaseCommand extends CamelCommand { run.excludes = excludes; run.openapi = openapi; run.download = download; + run.packageScanJars = packageScanJars; run.runtime = runtime; run.camelVersion = camelVersion; run.camelSpringBootVersion = camelSpringBootVersion; diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java index b4a0c2dcbe8..724ac94dd37 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java @@ -213,6 +213,10 @@ public class Run extends CamelCommand { description = "Whether to allow automatic downloading JAR dependencies (over the internet)") boolean download = true; + @CommandLine.Option(names = { "--package-scan-jars" }, defaultValue = "false", + description = "Whether to automatic package scan JARs for custom Spring or Quarkus beans making them available for Camel JBang") + boolean packageScanJars; + @Option(names = { "--jvm-debug" }, parameterConsumer = DebugConsumer.class, paramLabel = "<true|false|port>", description = "To enable JVM remote debugging on port 4004 by default. The supported values are true to " + "enable the remote debugging, false to disable the remote debugging or a number to use a custom port") @@ -552,6 +556,7 @@ public class Run extends CamelCommand { main.setRepositories(String.join(",", repositories)); } main.setDownload(download); + main.setPackageScanJars(packageScanJars); main.setFresh(fresh); main.setMavenSettings(mavenSettings); main.setMavenSettingsSecurity(mavenSettingsSecurity); @@ -1010,6 +1015,7 @@ public class Run extends CamelCommand { eq.addDependencies("camel:cli-connector"); eq.fresh = this.fresh; eq.download = this.download; + eq.packageScanJars = this.packageScanJars; eq.quiet = true; eq.logging = false; eq.loggingLevel = "off"; @@ -1086,6 +1092,7 @@ public class Run extends CamelCommand { } eq.fresh = this.fresh; eq.download = this.download; + eq.packageScanJars = this.packageScanJars; eq.quiet = true; eq.logging = false; eq.loggingLevel = "off"; @@ -1223,6 +1230,8 @@ public class Run extends CamelCommand { mavenApacheSnapshotEnabled ? "true" : "false")); openapi = answer.getProperty("camel.jbang.open-api", openapi); download = "true".equals(answer.getProperty("camel.jbang.download", download ? "true" : "false")); + packageScanJars + = "true".equals(answer.getProperty("camel.jbang.packageScanJars", packageScanJars ? "true" : "false")); background = "true".equals(answer.getProperty("camel.jbang.background", background ? "true" : "false")); backgroundWait = "true".equals(answer.getProperty("camel.jbang.backgroundWait", backgroundWait ? "true" : "false")); jvmDebugPort = parseJvmDebugPort(answer.getProperty("camel.jbang.jvmDebug", Integer.toString(jvmDebugPort))); diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java index 37c3031154c..1ff2cba6658 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java +++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java @@ -172,6 +172,7 @@ public class KubernetesExport extends Export { gradleWrapper = configurer.gradleWrapper; fresh = configurer.fresh; download = configurer.download; + packageScanJars = configurer.packageScanJars; quiet = configurer.quiet; logging = configurer.logging; loggingLevel = configurer.loggingLevel; @@ -583,6 +584,7 @@ public class KubernetesExport extends Export { boolean gradleWrapper, boolean fresh, boolean download, + boolean packageScanJars, boolean quiet, boolean logging, String loggingLevel, diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java index 9df633f1cac..418750fc82f 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java +++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java @@ -193,6 +193,14 @@ public class KubernetesRun extends KubernetesBaseCommand { @CommandLine.Option(names = { "--exclude" }, description = "Exclude files by name or pattern") List<String> excludes = new ArrayList<>(); + @CommandLine.Option(names = { "--download" }, defaultValue = "true", + description = "Whether to allow automatic downloading JAR dependencies (over the internet)") + boolean download = true; + + @CommandLine.Option(names = { "--package-scan-jars" }, defaultValue = "false", + description = "Whether to automatic package scan JARs for custom Spring or Quarkus beans making them available for Camel JBang") + boolean packageScanJars; + @CommandLine.Option(names = { "--maven-settings" }, description = "Optional location of Maven settings.xml file to configure servers, repositories, mirrors and proxies." + " If set to \"false\", not even the default ~/.m2/settings.xml will be used.") @@ -397,7 +405,8 @@ public class KubernetesRun extends KubernetesBaseCommand { true, false, true, - true, + download, + packageScanJars, (quiet || output != null), true, "info", diff --git a/dsl/camel-kamelet-main/pom.xml b/dsl/camel-kamelet-main/pom.xml index 638e5cf3c0a..1a626f49ec7 100644 --- a/dsl/camel-kamelet-main/pom.xml +++ b/dsl/camel-kamelet-main/pom.xml @@ -122,6 +122,10 @@ <groupId>org.apache.camel</groupId> <artifactId>camel-yaml-dsl</artifactId> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jandex</artifactId> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-catalog</artifactId> 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 148dca9e966..0508fb78b8d 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 @@ -119,6 +119,7 @@ public class KameletMain extends MainCommandLineSupport { protected final MainRegistry registry = new MainRegistry(); private String profile = "dev"; private boolean download = true; + private boolean packageScanJars; private String repositories; private boolean fresh; private boolean verbose; @@ -228,6 +229,17 @@ public class KameletMain extends MainCommandLineSupport { this.download = download; } + public boolean isPackageScanJars() { + return packageScanJars; + } + + /** + * Whether to automatic package scan JARs for custom Spring or Quarkus beans making them available for Camel JBang + */ + public void setPackageScanJars(boolean packageScanJars) { + this.packageScanJars = packageScanJars; + } + public String getRepositories() { return repositories; } @@ -489,8 +501,8 @@ public class KameletMain extends MainCommandLineSupport { // load camel component and custom health-checks answer.setLoadHealthChecks(true); - // annotation based dependency injection for camel/spring/quarkus annotations in DSLs and Java beans + // annotation based dependency injection for camel/spring/quarkus annotations in DSLs and Java beans boolean lazyBean = "true".equals(getInitialProperties().get(getInstanceType() + ".lazyBean")); new AnnotationDependencyInjection(answer, lazyBean); @@ -714,6 +726,7 @@ public class KameletMain extends MainCommandLineSupport { private MavenDependencyDownloader createMavenDependencyDownloader(ClassLoader dynamicCL, DefaultCamelContext answer) { KnownReposResolver knownRepos = new KnownReposResolver(); knownRepos.loadKnownDependencies(); + MavenDependencyDownloader downloader = new MavenDependencyDownloader(); downloader.setDownload(download); downloader.setKnownReposResolver(knownRepos); @@ -726,13 +739,12 @@ public class KameletMain extends MainCommandLineSupport { downloader.setMavenSettingsSecurity(mavenSettingsSecurity); downloader.setMavenCentralEnabled(mavenCentralEnabled); downloader.setMavenApacheSnapshotEnabled(mavenApacheSnapshotEnabled); - if (downloadListener != null) { downloader.addDownloadListener(downloadListener); } downloader.addDownloadListener(new AutoConfigureDownloadListener()); downloader.addArtifactDownloadListener(new TypeConverterLoaderDownloadListener()); - downloader.addArtifactDownloadListener(new BasePackageScanDownloadListener()); + downloader.addArtifactDownloadListener(new BasePackageScanDownloadListener(packageScanJars)); return downloader; } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/BasePackageScanDownloadListener.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/BasePackageScanDownloadListener.java index 4a8281d3110..daa31b4aee2 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/BasePackageScanDownloadListener.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/BasePackageScanDownloadListener.java @@ -17,29 +17,49 @@ package org.apache.camel.main.download; import java.io.File; +import java.io.FileInputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; +import java.util.function.Supplier; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Singleton; + +import javax.inject.Named; import org.apache.camel.CamelConfiguration; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Configuration; +import org.apache.camel.RuntimeCamelException; import org.apache.camel.spi.CamelBeanPostProcessor; import org.apache.camel.spi.PackageScanClassResolver; +import org.apache.camel.spi.Registry; +import org.apache.camel.spi.annotations.Component; import org.apache.camel.support.PluginHelper; +import org.apache.camel.util.FileUtil; +import org.apache.camel.util.IOHelper; +import org.apache.camel.util.StringHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; public class BasePackageScanDownloadListener implements ArtifactDownloadListener, CamelContextAware { private static final Logger LOG = LoggerFactory.getLogger(BasePackageScanDownloadListener.class); private CamelContext camelContext; - private final Set<String> scanned = new HashSet<>(); + private final boolean packageScanJars; + + public BasePackageScanDownloadListener(boolean packageScanJars) { + this.packageScanJars = packageScanJars; + } @Override public CamelContext getCamelContext() { @@ -55,15 +75,44 @@ public class BasePackageScanDownloadListener implements ArtifactDownloadListener public void onDownloadedFile(File file) { String basePackage = camelContext.getCamelContextExtension().getBasePackageScan(); if (basePackage != null) { - try { - basePackageScanConfiguration(basePackage, file); - } catch (Exception e) { - // ignore + packageScan(basePackage); + } + if (packageScanJars) { + String ext = FileUtil.onlyExt(file.getName(), true); + if ("jar".equals(ext)) { + try { + Set<String> packages = new HashSet<>(); + JarInputStream is = new JarInputStream(new FileInputStream(file)); + JarEntry entry; + while ((entry = is.getNextJarEntry()) != null) { + final String name = entry.getName().trim(); + if (!entry.isDirectory() && name.endsWith(".class")) { + packages.add(FileUtil.onlyPath(name)); + } + } + if (!packages.isEmpty()) { + String[] arr = packages.toArray(new String[0]); + packageScan(arr); + } + IOHelper.close(is); + } catch (Exception e) { + // ignore + } } } } - protected void basePackageScanConfiguration(String basePackage, File file) throws Exception { + public void packageScan(String... basePackage) { + try { + basePackageScanConfiguration(basePackage); + basePackageScanSpring(basePackage); + basePackageScanQuarkus(basePackage); + } catch (Exception e) { + // ignore + } + } + + protected void basePackageScanConfiguration(String... basePackage) throws Exception { Collection<CamelConfiguration> configs = new ArrayList<>(); // we only want to scan via isolated classloader PackageScanClassResolver pscr = PluginHelper.getPackageScanClassResolver(camelContext); @@ -102,4 +151,89 @@ public class BasePackageScanDownloadListener implements ArtifactDownloadListener } } + protected void basePackageScanQuarkus(String... basePackage) throws Exception { + // we only want to scan via isolated classloader + PackageScanClassResolver pscr = PluginHelper.getPackageScanClassResolver(camelContext); + Set<Class<?>> found = pscr.findAnnotated(Set.of(ApplicationScoped.class, Singleton.class), basePackage); + for (Class<?> clazz : found) { + // avoid duplicate if we scan other JARs that can same class from previous downloads + String fqn = clazz.getName(); + if (scanned.contains(fqn)) { + continue; + } else { + scanned.add(fqn); + } + + LOG.debug("Discovered Quarkus @ApplicationScoped/@Singleton class: {}", clazz); + + // @Named can dictate the name of the bean + String name = null; + Named named = clazz.getAnnotation(Named.class); + if (named != null) { + name = named.value(); + } + if (name == null || name.isBlank()) { + name = clazz.getSimpleName(); + // lower case first if using class name + name = StringHelper.decapitalize(name); + } + // must be lazy as we do not know if the bean is in use or not + Supplier<Object> supplier = () -> camelContext.getInjector().newInstance(clazz, true); + bindBean(camelContext, clazz, name, supplier, "Quarkus @ApplicationScoped/@Singleton"); + } + } + + protected void basePackageScanSpring(String... basePackage) throws Exception { + // we only want to scan via isolated classloader + PackageScanClassResolver pscr = PluginHelper.getPackageScanClassResolver(camelContext); + Set<Class<?>> found = pscr.findAnnotated(Set.of(Component.class, Service.class), basePackage); + for (Class<?> clazz : found) { + // avoid duplicate if we scan other JARs that can same class from previous downloads + String fqn = clazz.getName(); + if (scanned.contains(fqn)) { + continue; + } else { + scanned.add(fqn); + } + + LOG.debug("Discovered Spring @Component/@Service class: {}", clazz); + + String name = null; + var ann = clazz.getAnnotation(Component.class); + if (ann != null) { + name = ann.value(); + } else { + var ann2 = clazz.getAnnotation(Service.class); + if (ann2 != null) { + name = ann2.value(); + } + } + if (name == null || name.isBlank()) { + name = clazz.getSimpleName(); + // lower case first if using class name + name = StringHelper.decapitalize(name); + } + // must be lazy as we do not know if the bean is in use or not + Supplier<Object> supplier = () -> camelContext.getInjector().newInstance(clazz, true); + bindBean(camelContext, clazz, name, supplier, "Spring @Component/@Service"); + } + } + + private static void bindBean(CamelContext context, Class<?> type, String name, Supplier<Object> supplier, String kind) { + // to support hot reloading of beans then we need to enable unbind mode in bean post processor + Registry registry = context.getRegistry(); + CamelBeanPostProcessor bpp = PluginHelper.getBeanPostProcessor(context); + bpp.setUnbindEnabled(true); + try { + // re-bind the bean to the registry + registry.unbind(name); + LOG.debug("Lazy binding {} bean: {} of type: {}", kind, name, type); + registry.bind(name, type, supplier); + } catch (Exception e) { + throw RuntimeCamelException.wrapRuntimeException(e); + } finally { + bpp.setUnbindEnabled(false); + } + } + } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java index 07000bfa8aa..bb2a8892f99 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/injection/AnnotationDependencyInjection.java @@ -48,6 +48,7 @@ import org.apache.camel.spi.TypeConverterRegistry; import org.apache.camel.support.PluginHelper; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.ReflectionHelper; +import org.apache.camel.util.StringHelper; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -212,6 +213,11 @@ public final class AnnotationDependencyInjection { } else if (service != null && ObjectHelper.isNotEmpty(service.value())) { name = service.value(); } + if (name == null || name.isBlank()) { + name = clazz.getSimpleName(); + // lower case first if using class name + name = StringHelper.decapitalize(name); + } bindBean(camelContext, name, instance, true); } } @@ -292,6 +298,11 @@ public final class AnnotationDependencyInjection { if (named != null) { name = named.value(); } + if (name == null || name.isBlank()) { + name = clazz.getSimpleName(); + // lower case first if using class name + name = StringHelper.decapitalize(name); + } bindBean(camelContext, name, instance, true); } } diff --git a/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties b/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties index 1e2747ca73b..0d180bcdfac 100644 --- a/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties +++ b/dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties @@ -34,6 +34,7 @@ META-INF/services/org/apache/camel/modelyaml-dumper = camel:yaml-io META-INF/services/org/apache/camel/micrometer-prometheus = camel:micrometer-prometheus META-INF/services/org/apache/camel/cron/cron-service = camel:quartz META-INF/services/org/apache/camel/platform-http/jolokia = camel:camel-platform-http-jolokia +META-INF/services/org/apache/camel/jandex-class-resolver = camel:jandex org.apache.camel.component.activemq.ActiveMQComponent\:embedded\=true = org.apache.activemq:activemq-broker:5.19.0 org.apache.camel.component.activemq6.ActiveMQComponent\:embedded\=true = org.apache.activemq:activemq-broker:6.1.6 spring.datasource.url = org.springframework.boot:spring-boot-starter-jdbc:${spring-boot-version} diff --git a/parent/pom.xml b/parent/pom.xml index 80688746566..ce08ce7c659 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -1584,6 +1584,11 @@ <artifactId>camel-jacksonxml</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jandex</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jasypt</artifactId>