Skip to content

Commit

Permalink
Register fields for reflection in kubernetes-client
Browse files Browse the repository at this point in the history
Signed-off-by: Jorge Solórzano <[email protected]>
  • Loading branch information
jorsol committed Jul 23, 2024
1 parent e1e133f commit 01afb82
Showing 1 changed file with 20 additions and 56 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.quarkus.kubernetes.client.deployment;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -10,16 +9,12 @@
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.IndexView;
import org.jboss.jandex.Type;
import org.jboss.logging.Logger;

import com.fasterxml.jackson.annotation.JsonFormat;

import io.fabric8.kubernetes.api.builder.VisitableBuilder;
import io.fabric8.kubernetes.api.model.AnyType;
import io.fabric8.kubernetes.api.model.IntOrString;
Expand Down Expand Up @@ -68,16 +63,15 @@ public class KubernetesClientProcessor {
private static final DotName WATCHER = DotName.createSimple(Watcher.class.getName());
private static final DotName RESOURCE_EVENT_HANDLER = DotName
.createSimple(io.fabric8.kubernetes.client.informers.ResourceEventHandler.class.getName());
private static final DotName KUBERNETES_RESOURCE = DotName.createSimple(KubernetesResource.class.getName());
private static final DotName VALIDATION_SCHEMA = DotName.createSimple(ValidationSchema.class.getName());
private static final DotName KUBERNETES_RESOURCE = DotName
.createSimple(KubernetesResource.class.getName());
private static final DotName KUBERNETES_RESOURCE_LIST = DotName
.createSimple(KubernetesResourceList.class.getName());
private static final DotName KUBE_SCHEMA = DotName.createSimple(KubeSchema.class.getName());
private static final DotName VISITABLE_BUILDER = DotName.createSimple(VisitableBuilder.class.getName());
private static final DotName VALIDATION_SCHEMA = DotName.createSimple(ValidationSchema.class.getName());
private static final DotName KUBE_SCHEMA = DotName.createSimple(KubeSchema.class.getName());
private static final DotName CUSTOM_RESOURCE = DotName.createSimple(CustomResource.class.getName());
private static final String SERVICE_ACCOUNT = "ServiceAccount";

private static final DotName JSON_FORMAT = DotName.createSimple(JsonFormat.class.getName());
private static final String[] EMPTY_STRINGS_ARRAY = new String[0];

@BuildStep
Expand Down Expand Up @@ -159,31 +153,22 @@ public void process(ApplicationIndexBuildItem applicationIndex, CombinedIndexBui
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<>(
kubernetesResourceImpls.size() + kubernetesResourceListImpls.size());
List<String> withFieldsRegistration = new ArrayList<>(2);
List<DotName> ignoreJsonDeserialization = new ArrayList<>(
kubernetesResourceImpls.size() + kubernetesResourceListImpls.size());
int defSize = kubernetesResourceImpls.size() + kubernetesResourceListImpls.size() + visitableBuilderImpls.size();
List<String> withFieldsRegistration = new ArrayList<>(defSize);
List<DotName> ignoreJsonDeserialization = new ArrayList<>(defSize);

populateReflectionRegistrationLists(kubernetesResourceImpls, watchedClasses, ignoreJsonDeserialization,
withoutFieldsRegistration,
withFieldsRegistration);
populateReflectionRegistrationLists(kubernetesResourceListImpls, watchedClasses, ignoreJsonDeserialization,
withoutFieldsRegistration,
withFieldsRegistration);
populateReflectionRegistrationLists(visitableBuilderImpls, watchedClasses, ignoreJsonDeserialization,
withoutFieldsRegistration,
withFieldsRegistration);

if (!withFieldsRegistration.isEmpty()) {
reflectiveClasses.produce(ReflectiveClassBuildItem
.builder(withFieldsRegistration.toArray(EMPTY_STRINGS_ARRAY)).weak(true).methods().fields()
.build());
}
if (!withoutFieldsRegistration.isEmpty()) {
reflectiveClasses.produce(ReflectiveClassBuildItem
.builder(withoutFieldsRegistration.toArray(EMPTY_STRINGS_ARRAY)).weak(true).methods()
.build());
reflectiveClasses.produce(ReflectiveClassBuildItem
.builder(withFieldsRegistration.toArray(EMPTY_STRINGS_ARRAY))
.weak().methods().fields()
.build());
}

ignoredJsonDeserializationClasses.produce(new IgnoreJsonDeserializeClassBuildItem(ignoreJsonDeserialization));
Expand Down Expand Up @@ -233,9 +218,8 @@ public void process(ApplicationIndexBuildItem applicationIndex, CombinedIndexBui
.sorted()
.collect(Collectors.joining("\n"));
log.debugv("Watched Classes:\n{0}", watchedClassNames);
List<String> modelClasses = new ArrayList<>(withFieldsRegistration.size() + withoutFieldsRegistration.size());
List<String> modelClasses = new ArrayList<>(withFieldsRegistration.size());
modelClasses.addAll(withFieldsRegistration);
modelClasses.addAll(withoutFieldsRegistration);
Collections.sort(modelClasses);
log.debugv("Model Classes:\n{0}", String.join("\n", modelClasses));
}
Expand All @@ -254,35 +238,15 @@ public void process(ApplicationIndexBuildItem applicationIndex, CombinedIndexBui
private static void populateReflectionRegistrationLists(Collection<ClassInfo> kubernetesResourceImpls,
Set<DotName> watchedClasses,
List<DotName> ignoredJsonDeserializationClasses,
List<String> withoutFieldsRegistration,
List<String> withFieldsRegistration) {
kubernetesResourceImpls
.stream()
.peek(c -> {
// we need to make sure that the Jackson extension does not try to fully register the model classes
// since we are going to register them weakly
ignoredJsonDeserializationClasses.add(c.name());
})
.filter(c -> !watchedClasses.contains(c.name()))
.map(c -> {
boolean registerFields = false;
List<AnnotationInstance> jsonFormatInstances = c.annotationsMap().get(JSON_FORMAT);
if (jsonFormatInstances != null) {
for (AnnotationInstance jsonFormatInstance : jsonFormatInstances) {
if (jsonFormatInstance.target().kind() == AnnotationTarget.Kind.FIELD) {
registerFields = true;
break;
}
}
}
return new AbstractMap.SimpleEntry<>(c.name(), registerFields);
}).forEach(e -> {
if (e.getValue()) {
withFieldsRegistration.add(e.getKey().toString());
} else {
withoutFieldsRegistration.add(e.getKey().toString());
}
});
for (ClassInfo resource : kubernetesResourceImpls) {
// we need to make sure that the Jackson extension does not try to fully
// register the model classes since we are going to register them weakly
ignoredJsonDeserializationClasses.add(resource.name());
if (!watchedClasses.contains(resource.name())) {
withFieldsRegistration.add(resource.name().toString());
}
}
}

private void findWatchedClasses(final DotName implementedOrExtendedClass,
Expand Down

0 comments on commit 01afb82

Please sign in to comment.