Skip to content

Commit

Permalink
Extend scan for CustomResources to full index, instead of simply appl…
Browse files Browse the repository at this point in the history
…ication index
  • Loading branch information
metacosm committed Feb 5, 2024
1 parent de74fa3 commit aab4cc5
Showing 1 changed file with 28 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Type;
import org.jboss.jandex.*;
import org.jboss.logging.Logger;

import com.fasterxml.jackson.annotation.JsonFormat;
Expand Down Expand Up @@ -122,19 +118,22 @@ public void process(ApplicationIndexBuildItem applicationIndex, CombinedIndexBui

// register fully (and not weakly) for reflection watchers, informers and custom resources
final Set<DotName> watchedClasses = new HashSet<>();
findWatchedClasses(WATCHER, applicationIndex, combinedIndexBuildItem, watchedClasses, 1,
true);
findWatchedClasses(RESOURCE_EVENT_HANDLER, applicationIndex, combinedIndexBuildItem, watchedClasses, 1,
true);
findWatchedClasses(CUSTOM_RESOURCE, applicationIndex, combinedIndexBuildItem, watchedClasses, 2,
false);
final var appIndex = applicationIndex.getIndex();
final var fullIndex = combinedIndexBuildItem.getIndex();
findWatchedClasses(WATCHER, watchedClasses, 1, true, appIndex, fullIndex);
findWatchedClasses(RESOURCE_EVENT_HANDLER, watchedClasses, 1, true, appIndex, fullIndex);
// in the case of CustomResources, we want to search the full index to also take into account additional
// dependencies that might not be in the application index, the most common use case being the model classes
// being defined in a separate module for reuse and indexed separately, which would cause the CustomResource
// implementations to not appear in the application index
findWatchedClasses(CUSTOM_RESOURCE, watchedClasses, 2, false, fullIndex, fullIndex);

Predicate<DotName> reflectionIgnorePredicate = ReflectiveHierarchyBuildItem.DefaultIgnoreTypePredicate.INSTANCE;
for (DotName className : watchedClasses) {
if (reflectionIgnorePredicate.test(className)) {
continue;
}
final ClassInfo watchedClass = combinedIndexBuildItem.getIndex().getClassByName(className);
final ClassInfo watchedClass = fullIndex.getClassByName(className);
if (watchedClass == null) {
log.warnv("Unable to lookup class: {0}", className);
} else {
Expand All @@ -147,12 +146,9 @@ public void process(ApplicationIndexBuildItem applicationIndex, CombinedIndexBui
}
}

Collection<ClassInfo> kubernetesResourceImpls = combinedIndexBuildItem.getIndex()
.getAllKnownImplementors(KUBERNETES_RESOURCE);
Collection<ClassInfo> kubernetesResourceListImpls = combinedIndexBuildItem.getIndex()
.getAllKnownImplementors(KUBERNETES_RESOURCE_LIST);
Collection<ClassInfo> visitableBuilderImpls = combinedIndexBuildItem.getIndex()
.getAllKnownImplementors(VISITABLE_BUILDER);
Collection<ClassInfo> kubernetesResourceImpls = fullIndex.getAllKnownImplementors(KUBERNETES_RESOURCE);
Collection<ClassInfo> kubernetesResourceListImpls = fullIndex.getAllKnownImplementors(KUBERNETES_RESOURCE_LIST);
Collection<ClassInfo> visitableBuilderImpls = fullIndex.getAllKnownImplementors(VISITABLE_BUILDER);

// default sizes determined experimentally - these are only set in order to prevent continuous expansion of the array list
List<String> withoutFieldsRegistration = new ArrayList<>(
Expand Down Expand Up @@ -185,21 +181,19 @@ public void process(ApplicationIndexBuildItem applicationIndex, CombinedIndexBui
ignoredJsonDeserializationClasses.produce(new IgnoreJsonDeserializeClassBuildItem(ignoreJsonDeserialization));

// we also ignore some classes that are annotated with @JsonDeserialize that would force the registration of the entire model
ignoredJsonDeserializationClasses.produce(
new IgnoreJsonDeserializeClassBuildItem(KUBE_SCHEMA));
ignoredJsonDeserializationClasses.produce(
new IgnoreJsonDeserializeClassBuildItem(KUBERNETES_RESOURCE_LIST));
ignoredJsonDeserializationClasses.produce(new IgnoreJsonDeserializeClassBuildItem(KUBE_SCHEMA));
ignoredJsonDeserializationClasses.produce(new IgnoreJsonDeserializeClassBuildItem(KUBERNETES_RESOURCE_LIST));
ignoredJsonDeserializationClasses.produce(new IgnoreJsonDeserializeClassBuildItem(KUBERNETES_RESOURCE));

final String[] deserializerClasses = combinedIndexBuildItem.getIndex()
final String[] deserializerClasses = fullIndex
.getAllKnownSubclasses(DotName.createSimple("com.fasterxml.jackson.databind.JsonDeserializer"))
.stream()
.map(c -> c.name().toString())
.filter(s -> s.startsWith("io.fabric8.kubernetes"))
.toArray(String[]::new);
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(deserializerClasses).methods().build());

final String[] serializerClasses = combinedIndexBuildItem.getIndex()
final String[] serializerClasses = fullIndex
.getAllKnownSubclasses(DotName.createSimple("com.fasterxml.jackson.databind.JsonSerializer"))
.stream()
.map(c -> c.name().toString())
Expand Down Expand Up @@ -277,16 +271,17 @@ private static void populateReflectionRegistrationLists(Collection<ClassInfo> ku
});
}

private void findWatchedClasses(final DotName implementedOrExtendedClass, final ApplicationIndexBuildItem applicationIndex,
final CombinedIndexBuildItem combinedIndexBuildItem, final Set<DotName> watchedClasses,
final int expectedGenericTypeCardinality, boolean isTargetClassAnInterface) {
final var index = applicationIndex.getIndex();
final var implementors = isTargetClassAnInterface ? index
.getAllKnownImplementors(implementedOrExtendedClass) : index.getAllKnownSubclasses(implementedOrExtendedClass);
private void findWatchedClasses(final DotName implementedOrExtendedClass,
final Set<DotName> watchedClasses, final int expectedGenericTypeCardinality, boolean isTargetClassAnInterface,
IndexView targetIndex,
IndexView fullIndex) {

final var implementors = isTargetClassAnInterface ? targetIndex.getAllKnownImplementors(implementedOrExtendedClass)
: targetIndex.getAllKnownSubclasses(implementedOrExtendedClass);
implementors.forEach(c -> {
try {
final List<Type> watcherGenericTypes = JandexUtil.resolveTypeParameters(c.name(),
implementedOrExtendedClass, combinedIndexBuildItem.getIndex());
final List<Type> watcherGenericTypes = JandexUtil.resolveTypeParameters(c.name(), implementedOrExtendedClass,
fullIndex);
if (!isTargetClassAnInterface) {
// add the class itself: for example, in the case of CustomResource, we want to
// register the class that extends CustomResource in addition to its type parameters
Expand All @@ -298,7 +293,7 @@ private void findWatchedClasses(final DotName implementedOrExtendedClass, final
} catch (IllegalArgumentException ignored) {
// when the class has no subclasses and we were not able to determine the generic types,
// it's likely that the class might be able to get deserialized
if (index.getAllKnownSubclasses(c.name()).isEmpty()) {
if (targetIndex.getAllKnownSubclasses(c.name()).isEmpty()) {
log.warnv("{0} '{1}' will most likely not work correctly in native mode. " +
"Consider specifying the generic type of '{2}' that this class handles. "
+
Expand Down

0 comments on commit aab4cc5

Please sign in to comment.