This is an automated email from the ASF dual-hosted git repository.

ppalaga pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new 10c8517  Skip querying Jandex for 
quarkus.camel.native.reflection.include-patterns that have no wildcards fix 
#2970
10c8517 is described below

commit 10c8517be05ae2d006633f7c78620debfb2708bf
Author: Peter Palaga <[email protected]>
AuthorDate: Mon Aug 2 21:11:54 2021 +0200

    Skip querying Jandex for quarkus.camel.native.reflection.include-patterns 
that have no wildcards fix #2970
---
 .../ROOT/pages/reference/extensions/core.adoc      |  5 +-
 .../core/deployment/CamelNativeImageProcessor.java | 17 +++---
 .../quarkus/core/deployment/util/PathFilter.java   | 67 +++++++++++++++++-----
 .../core/deployment/util/PathFilterTest.java       | 25 ++++++--
 .../org/apache/camel/quarkus/core/CamelConfig.java | 12 ++--
 .../apache/camel/quarkus/core/CoreResource.java    |  3 +-
 .../core/src/main/resources/application.properties |  2 +-
 .../org/apache/camel/quarkus/core/CoreTest.java    | 13 +++++
 8 files changed, 108 insertions(+), 36 deletions(-)

diff --git a/docs/modules/ROOT/pages/reference/extensions/core.adoc 
b/docs/modules/ROOT/pages/reference/extensions/core.adoc
index c649dc9..87a8e4c 100644
--- a/docs/modules/ROOT/pages/reference/extensions/core.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/core.adoc
@@ -220,7 +220,10 @@ A comma separated list of Ant-path style patterns to match 
class names that shou
  By default, no classes are included. The set selected by this option can be 
narrowed down by `exclude-patterns`. 
  Note that Quarkus extensions typically register the required classes for 
reflection by themselves. This option is useful in situations when the built in 
functionality is not sufficient. 
  Note that this option enables the full reflective access for constructors, 
fields and methods. If you need a finer grained control, consider using 
`io.quarkus.runtime.annotations.RegisterForReflection` annotation in your Java 
code. 
- For this option to work properly, the artifacts containing the selected 
classes must either contain a Jandex index (`META-INF/jandex.idx`) or they must 
be registered for indexing using the `quarkus.index-dependency.++*++` family of 
options in `application.properties` - e.g. 
quarkus.index-dependency.my-dep.group-id = org.my-group 
quarkus.index-dependency.my-dep.artifact-id = my-artifact  where `my-dep` is a 
label of your choice to tell Quarkus that `org.my-group` and with `my-artifact` 
b [...]
+ For this option to work properly, at least one of the following conditions 
must be satisfied:  
+ - There are no wildcards (`++*++` or `/`) in the patterns 
+ - The artifacts containing the selected classes contain a Jandex index 
(`META-INF/jandex.idx`) 
+ - The artifacts containing the selected classes are registered for indexing 
using the `quarkus.index-dependency.++*++` family of options in 
`application.properties` - e.g. quarkus.index-dependency.my-dep.group-id = 
org.my-group quarkus.index-dependency.my-dep.artifact-id = my-artifact  where 
`my-dep` is a label of your choice to tell Quarkus that `org.my-group` and with 
`my-artifact` belong together.
 | `string`
 | 
 
diff --git 
a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelNativeImageProcessor.java
 
b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelNativeImageProcessor.java
index 548f6df..34e8bd9 100644
--- 
a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelNativeImageProcessor.java
+++ 
b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelNativeImageProcessor.java
@@ -249,17 +249,14 @@ public class CamelNativeImageProcessor {
                 .forEach(builder::exclude);
         final PathFilter pathFilter = builder.build();
 
-        for (ApplicationArchive archive : 
archives.getAllApplicationArchives()) {
-            LOGGER.debug("Scanning resources for native inclusion from archive 
at {}", archive.getPaths());
-
-            for (Path rootPath : archive.getRootDirs()) {
-                String[] selectedClassNames = 
pathFilter.scanClassNames(rootPath, CamelSupport.safeWalk(rootPath),
-                        Files::isRegularFile);
-                if (selectedClassNames.length > 0) {
-                    reflectiveClasses.produce(new 
ReflectiveClassBuildItem(true, true, selectedClassNames));
-                }
-            }
+        Stream<Path> archiveRootDirs = 
archives.getAllApplicationArchives().stream()
+                .peek(archive -> LOGGER.debug("Scanning resources for native 
inclusion from archive at {}", archive.getPaths()))
+                .flatMap(archive -> archive.getRootDirs().toList().stream());
+        String[] selectedClassNames = 
pathFilter.scanClassNames(archiveRootDirs);
+        if (selectedClassNames.length > 0) {
+            reflectiveClasses.produce(new ReflectiveClassBuildItem(true, true, 
selectedClassNames));
         }
+
     }
 
     @BuildStep
diff --git 
a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/util/PathFilter.java
 
b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/util/PathFilter.java
index f82ce6d..31965b1 100644
--- 
a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/util/PathFilter.java
+++ 
b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/util/PathFilter.java
@@ -16,12 +16,17 @@
  */
 package org.apache.camel.quarkus.core.deployment.util;
 
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import org.apache.camel.util.AntPathMatcher;
@@ -36,11 +41,14 @@ public class PathFilter {
     private static final int CLASS_SUFFIX_LENGTH = CLASS_SUFFIX.length();
 
     private final AntPathMatcher matcher = new AntPathMatcher();
+    private final List<String> includePaths;
     private final List<String> includePatterns;
     private final List<String> excludePatterns;
     private final Predicate<String> stringPredicate;
 
     PathFilter(List<String> includePatterns, List<String> excludePatterns) {
+        super();
+        this.includePaths = includePatterns.stream().filter(path -> 
!isPattern(path)).collect(Collectors.toList());
         this.includePatterns = includePatterns;
         this.excludePatterns = excludePatterns;
 
@@ -49,22 +57,17 @@ public class PathFilter {
         } else {
             this.stringPredicate = path -> {
                 path = sanitize(path);
-                // same logic as  org.apache.camel.main.DefaultRoutesCollector 
so exclude
+                // same logic as org.apache.camel.main.DefaultRoutesCollector 
so exclude
                 // take precedence over include
-                for (String part : excludePatterns) {
-                    if (matcher.match(part, path)) {
-                        return false;
-                    }
+                if (matchesAny(path, excludePatterns)) {
+                    return false;
                 }
-                for (String part : includePatterns) {
-                    if (matcher.match(part, path)) {
-                        return true;
-                    }
+                if (matchesAny(path, includePatterns)) {
+                    return true;
                 }
                 return ObjectHelper.isEmpty(includePatterns);
             };
         }
-        ;
     }
 
     public Predicate<String> asStringPredicate() {
@@ -87,8 +90,29 @@ public class PathFilter {
         }
     }
 
-    public String[] scanClassNames(Path rootPath, Stream<Path> pathStream, 
Predicate<Path> isRegularFile) {
-        return pathStream
+    public String[] scanClassNames(Stream<Path> archiveRootDirs) {
+        final Set<String> selectedPaths = new TreeSet<>();
+        archiveRootDirs.forEach(rootDir -> scanClassNames(rootDir, 
CamelSupport.safeWalk(rootDir),
+                Files::isRegularFile, selectedPaths::add));
+        /* Let's add the paths without wildcards even if they did not match 
any Jandex class
+         * A workaround for 
https://github.com/apache/camel-quarkus/issues/2969 */
+        addNonPatternPaths(selectedPaths);
+        return selectedPaths.toArray(new String[0]);
+    }
+
+    void addNonPatternPaths(final Set<String> selectedPaths) {
+        if (!includePaths.isEmpty()) {
+            for (String path : includePaths) {
+                if (!selectedPaths.contains(path) && !matchesAny(path, 
excludePatterns)) {
+                    selectedPaths.add(path.replace('/', '.'));
+                }
+            }
+        }
+    }
+
+    void scanClassNames(Path rootPath, Stream<Path> pathStream, 
Predicate<Path> isRegularFile,
+            Consumer<String> resultConsumer) {
+        pathStream
                 .filter(isRegularFile)
                 .filter(path -> 
path.getFileName().toString().endsWith(CLASS_SUFFIX))
                 .map(rootPath::relativize)
@@ -96,7 +120,16 @@ public class PathFilter {
                 .map(stringPath -> stringPath.substring(0, stringPath.length() 
- CLASS_SUFFIX_LENGTH))
                 .filter(stringPredicate)
                 .map(slashClassName -> slashClassName.replace('/', '.'))
-                .toArray(String[]::new);
+                .forEach(resultConsumer::accept);
+    }
+
+    boolean matchesAny(String path, List<String> patterns) {
+        for (String part : patterns) {
+            if (matcher.match(part, path)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     static String sanitize(String path) {
@@ -106,6 +139,10 @@ public class PathFilter {
                 : path;
     }
 
+    static boolean isPattern(String path) {
+        return path.indexOf('*') != -1 || path.indexOf('?') != -1;
+    }
+
     public static class Builder {
         private List<String> includePatterns = new ArrayList<>();
         private List<String> excludePatterns = new ArrayList<>();
@@ -125,7 +162,7 @@ public class PathFilter {
         }
 
         public Builder include(Collection<String> patterns) {
-            
patterns.stream().map(PathFilter::sanitize).forEach(includePatterns::add);
+            patterns.stream().forEach(this::include);
             return this;
         }
 
@@ -140,7 +177,7 @@ public class PathFilter {
         }
 
         public Builder exclude(Collection<String> patterns) {
-            
patterns.stream().map(PathFilter::sanitize).forEach(excludePatterns::add);
+            patterns.stream().forEach(this::exclude);
             return this;
         }
 
diff --git 
a/extensions-core/core/deployment/src/test/java/org/apache/camel/quarkus/core/deployment/util/PathFilterTest.java
 
b/extensions-core/core/deployment/src/test/java/org/apache/camel/quarkus/core/deployment/util/PathFilterTest.java
index 133d7b6..7b7e16b 100644
--- 
a/extensions-core/core/deployment/src/test/java/org/apache/camel/quarkus/core/deployment/util/PathFilterTest.java
+++ 
b/extensions-core/core/deployment/src/test/java/org/apache/camel/quarkus/core/deployment/util/PathFilterTest.java
@@ -20,6 +20,8 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 
@@ -118,14 +120,29 @@ public class PathFilterTest {
                 .map(rootPath::resolve);
 
         final Predicate<Path> isRegularFile = path -> 
path.getFileName().toString().contains(".");
-        final String[] classNames = filter.scanClassNames(rootPath, 
pathStream, isRegularFile);
+        final Set<String> classNames = new TreeSet<>();
+        filter.scanClassNames(rootPath, pathStream, isRegularFile, 
classNames::add);
 
-        Assertions.assertArrayEquals(new String[] {
+        Assertions.assertEquals(new TreeSet<>(Arrays.asList(
                 "org.p1.Class1",
                 "org.p1.Class1$Inner",
-                "org.p2.whatever.Class2"
-        }, classNames);
+                "org.p2.whatever.Class2")),
+                classNames);
 
     }
 
+    @Test
+    void addNonPatternPaths() {
+        final PathFilter pathFilter = new PathFilter.Builder()
+                .include("org/p1/*")
+                .include("org/p2/**")
+                .include("org/p3/NonPatternClass")
+                .exclude("org/p1/ExcludedClass")
+                .exclude("org/p2/excludedpackage/**")
+                .build();
+        Set<String> selectedPaths = new TreeSet<>();
+        pathFilter.addNonPatternPaths(selectedPaths);
+        Assertions.assertEquals(new 
TreeSet<>(Arrays.asList("org.p3.NonPatternClass")), selectedPaths);
+    }
+
 }
diff --git 
a/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelConfig.java
 
b/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelConfig.java
index 0d8a6bc..4288399 100644
--- 
a/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelConfig.java
+++ 
b/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelConfig.java
@@ -265,9 +265,12 @@ public class CamelConfig {
          * <code>io.quarkus.runtime.annotations.RegisterForReflection</code> 
annotation
          * in your Java code.
          * <p>
-         * For this option to work properly, the artifacts containing the 
selected classes
-         * must either contain a Jandex index ({@code META-INF/jandex.idx}) or 
they must
-         * be registered for indexing using the {@code 
quarkus.index-dependency.*} family
+         * For this option to work properly, at least one of the following 
conditions must be satisfied:
+         * <ul>
+         * <li>There are no wildcards (<code>*</code> or <code>/</code>) in 
the patterns</li>
+         * <li>The artifacts containing the selected classes contain a Jandex 
index ({@code META-INF/jandex.idx})</li>
+         * <li>The artifacts containing the selected classes are registered 
for indexing using the
+         * {@code quarkus.index-dependency.*} family
          * of options in {@code application.properties} - e.g.
          *
          * <pre>
@@ -276,7 +279,8 @@ public class CamelConfig {
          * </pre>
          *
          * where {@code my-dep} is a label of your choice to tell Quarkus that
-         * {@code org.my-group} and with {@code my-artifact} belong together.
+         * {@code org.my-group} and with {@code my-artifact} belong 
together.</li>
+         * </ul>
          */
         @ConfigItem
         public Optional<List<String>> includePatterns;
diff --git 
a/integration-test-groups/foundation/core/src/main/java/org/apache/camel/quarkus/core/CoreResource.java
 
b/integration-test-groups/foundation/core/src/main/java/org/apache/camel/quarkus/core/CoreResource.java
index c576fd1..336af06 100644
--- 
a/integration-test-groups/foundation/core/src/main/java/org/apache/camel/quarkus/core/CoreResource.java
+++ 
b/integration-test-groups/foundation/core/src/main/java/org/apache/camel/quarkus/core/CoreResource.java
@@ -185,13 +185,14 @@ public class CoreResource {
             @PathParam("methodName") String methodName,
             @PathParam("value") String value) {
         try {
-            final Class<?> cl = Class.forName(className);
+            final Class<?> cl = Class.forName(className, true, 
Thread.currentThread().getContextClassLoader());
             final Object inst = cl.newInstance();
             final Method method = cl.getDeclaredMethod(methodName, 
Object.class);
             method.invoke(inst, value);
             return Response.ok(inst.toString()).build();
         } catch (ClassNotFoundException | InstantiationException | 
IllegalAccessException | NoSuchMethodException
                 | SecurityException | IllegalArgumentException | 
InvocationTargetException e) {
+            e.printStackTrace();
             return Response.serverError().entity(e.getClass().getName() + ": " 
+ e.getMessage()).build();
         }
     }
diff --git 
a/integration-test-groups/foundation/core/src/main/resources/application.properties
 
b/integration-test-groups/foundation/core/src/main/resources/application.properties
index 1a377ea..9649983 100644
--- 
a/integration-test-groups/foundation/core/src/main/resources/application.properties
+++ 
b/integration-test-groups/foundation/core/src/main/resources/application.properties
@@ -20,7 +20,7 @@
 #
 quarkus.index-dependency.commons-lang3.group-id = org.apache.commons
 quarkus.index-dependency.commons-lang3.artifact-id = commons-lang3
-quarkus.camel.native.reflection.include-patterns = 
org.apache.commons.lang3.tuple.*
+quarkus.camel.native.reflection.include-patterns = 
org.apache.commons.lang3.tuple.*,java.lang.StringBuffer
 quarkus.camel.native.reflection.exclude-patterns = 
org.apache.commons.lang3.tuple.*Triple
 
 #
diff --git 
a/integration-test-groups/foundation/core/src/test/java/org/apache/camel/quarkus/core/CoreTest.java
 
b/integration-test-groups/foundation/core/src/test/java/org/apache/camel/quarkus/core/CoreTest.java
index 0a223cc..af26798 100644
--- 
a/integration-test-groups/foundation/core/src/test/java/org/apache/camel/quarkus/core/CoreTest.java
+++ 
b/integration-test-groups/foundation/core/src/test/java/org/apache/camel/quarkus/core/CoreTest.java
@@ -95,6 +95,19 @@ public class CoreTest {
     }
 
     @Test
+    void reflectiveJreClass() {
+        RestAssured.when()
+                .get(
+                        
"/core/reflection/{className}/method/{methodName}/{value}",
+                        "java.lang.StringBuffer",
+                        "append",
+                        "This is a StringBuffer")
+                .then()
+                .statusCode(200)
+                .body(is("This is a StringBuffer"));
+    }
+
+    @Test
     void testDefaultHeadersMapFactoryConfigured() {
         
RestAssured.when().get("/core/headersmap-factory").then().body(is("true"));
     }

Reply via email to