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"));
}