Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraphQL - make sure the panache entities are updated in the index #19883

Merged
merged 1 commit into from
Sep 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion extensions/smallrye-graphql/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-graphql</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
package io.quarkus.smallrye.graphql.deployment;

import java.util.Collection;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.MethodParameterInfo;
import org.jboss.jandex.ModuleInfo;
import org.jboss.jandex.RecordComponentInfo;
import org.jboss.jandex.Type;

public class OverridableIndex implements IndexView {

private final IndexView original;
private final IndexView override;

private OverridableIndex(IndexView original, IndexView override) {
this.original = original;
this.override = override;
}

public static OverridableIndex create(IndexView original, IndexView override) {
return new OverridableIndex(original, override);
}

@Override
public Collection<ClassInfo> getKnownClasses() {
return overrideCollection(original.getKnownClasses(), override.getKnownClasses(), classInfoComparator);
}

@Override
public ClassInfo getClassByName(DotName dn) {
return overrideObject(original.getClassByName(dn), override.getClassByName(dn));
}

@Override
public Collection<ClassInfo> getKnownDirectSubclasses(DotName dn) {
return overrideCollection(original.getKnownDirectSubclasses(dn), override.getKnownDirectSubclasses(dn),
classInfoComparator);
}

@Override
public Collection<ClassInfo> getAllKnownSubclasses(DotName dn) {
return overrideCollection(original.getAllKnownSubclasses(dn), override.getAllKnownSubclasses(dn), classInfoComparator);
}

@Override
public Collection<ClassInfo> getKnownDirectImplementors(DotName dn) {
return overrideCollection(original.getKnownDirectImplementors(dn), override.getKnownDirectImplementors(dn),
classInfoComparator);
}

@Override
public Collection<ClassInfo> getAllKnownImplementors(DotName dn) {
return overrideCollection(original.getAllKnownImplementors(dn), override.getAllKnownImplementors(dn),
classInfoComparator);
}

@Override
public Collection<AnnotationInstance> getAnnotations(DotName dn) {
return overrideCollection(original.getAnnotations(dn), override.getAnnotations(dn), annotationInstanceComparator);
}

@Override
public Collection<AnnotationInstance> getAnnotationsWithRepeatable(DotName dn, IndexView iv) {
return overrideCollection(original.getAnnotationsWithRepeatable(dn, iv), override.getAnnotationsWithRepeatable(dn, iv),
annotationInstanceComparator);
}

@Override
public Collection<ModuleInfo> getKnownModules() {
return overrideCollection(original.getKnownModules(), override.getKnownModules(), moduleInfoComparator);
}

@Override
public ModuleInfo getModuleByName(DotName dn) {
return overrideObject(original.getModuleByName(dn), override.getModuleByName(dn));
}

@Override
public Collection<ClassInfo> getKnownUsers(DotName dn) {
return overrideCollection(original.getKnownUsers(dn), override.getKnownUsers(dn), classInfoComparator);
}

private Comparator<ClassInfo> classInfoComparator = new Comparator<ClassInfo>() {
@Override
public int compare(ClassInfo t, ClassInfo t1) {
return t.name().toString().compareTo(t1.name().toString());
}
};

private Comparator<Type> typeComparator = new Comparator<Type>() {
@Override
public int compare(Type t, Type t1) {
return t.name().toString().compareTo(t1.name().toString());
}
};

private Comparator<ModuleInfo> moduleInfoComparator = new Comparator<ModuleInfo>() {
@Override
public int compare(ModuleInfo t, ModuleInfo t1) {
return t.name().toString().compareTo(t1.name().toString());
}
};

private Comparator<FieldInfo> fieldInfoComparator = new Comparator<FieldInfo>() {
@Override
public int compare(FieldInfo t, FieldInfo t1) {
if (classInfoComparator.compare(t.declaringClass(), t1.declaringClass()) == 0) { // Same class
return t.name().toString().compareTo(t1.name().toString());
}
return -1;
}
};

private Comparator<RecordComponentInfo> recordComponentInfoComparator = new Comparator<RecordComponentInfo>() {
@Override
public int compare(RecordComponentInfo t, RecordComponentInfo t1) {
if (classInfoComparator.compare(t.declaringClass(), t1.declaringClass()) == 0) { // Same class
return t.name().toString().compareTo(t1.name().toString());
}
return -1;
}
};

private Comparator<MethodInfo> methodInfoComparator = new Comparator<MethodInfo>() {
@Override
public int compare(MethodInfo t, MethodInfo t1) {
if (classInfoComparator.compare(t.declaringClass(), t1.declaringClass()) == 0) { // Same class
if (t.name().toString().compareTo(t1.name().toString()) == 0) { // Same method name
if (t.parameters().size() == t1.parameters().size()) { // Same number of parameters
for (int i = 0; i < t.parameters().size(); i++) {
int typeTheSame = typeComparator.compare(t.parameters().get(i), t1.parameters().get(i));
if (typeTheSame != 0) {
return typeTheSame;
}
}
// All parameter type are the same
return 0;
}
}
}
return -1;
}
};

private Comparator<MethodParameterInfo> methodParameterInfoComparator = new Comparator<MethodParameterInfo>() {
@Override
public int compare(MethodParameterInfo t, MethodParameterInfo t1) {
if (methodInfoComparator.compare(t.method(), t1.method()) == 0 && // Same method
t.kind().equals(t1.kind()) && // Same kind
t.name().equals(t1.name()) && // Same name
t.position() == t1.position()) { // Same position
return 0;
}
return -1;
}
};

private Comparator<AnnotationInstance> annotationInstanceComparator = new Comparator<AnnotationInstance>() {
@Override
public int compare(AnnotationInstance t, AnnotationInstance t1) {
if (t.name().equals(t1.name())) {
// Class Info
if (t.target().kind().equals(AnnotationTarget.Kind.CLASS)
&& t1.target().kind().equals(AnnotationTarget.Kind.CLASS)) {
return classInfoComparator.compare(t.target().asClass(), t1.target().asClass());
}

// Field Info
if (t.target().kind().equals(AnnotationTarget.Kind.FIELD)
&& t1.target().kind().equals(AnnotationTarget.Kind.FIELD)) {
return fieldInfoComparator.compare(t.target().asField(), t1.target().asField());
}

// Type
if (t.target().kind().equals(AnnotationTarget.Kind.TYPE)
&& t1.target().kind().equals(AnnotationTarget.Kind.TYPE)) {
return typeComparator.compare(t.target().asType().target(), t1.target().asType().target());
}

// Method Info
if (t.target().kind().equals(AnnotationTarget.Kind.METHOD)
&& t1.target().kind().equals(AnnotationTarget.Kind.METHOD)) {
return methodInfoComparator.compare(t.target().asMethod(), t1.target().asMethod());
}

// Method Parameter
if (t.target().kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER)
&& t1.target().kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER)) {
return methodParameterInfoComparator.compare(t.target().asMethodParameter(),
t1.target().asMethodParameter());
}

// Record
if (t.target().kind().equals(AnnotationTarget.Kind.RECORD_COMPONENT)
&& t1.target().kind().equals(AnnotationTarget.Kind.RECORD_COMPONENT)) {
return recordComponentInfoComparator.compare(t.target().asRecordComponent(),
t1.target().asRecordComponent());
}
}
return -1;
}
};

private <T> Collection<T> overrideCollection(Collection<T> originalCollection, Collection<T> overrideCollection,
Comparator<T> comparator) {
if (originalCollection == null && overrideCollection == null) {
return null;
}

if (originalCollection == null) {
return overrideCollection;
}
if (overrideCollection == null) {
return originalCollection;
}

if (originalCollection.isEmpty() && overrideCollection.isEmpty()) {
return originalCollection;
}

if (originalCollection.isEmpty()) {
return overrideCollection;
}
if (overrideCollection.isEmpty()) {
return originalCollection;
}

Set<T> newCollection = new TreeSet<>(comparator);
newCollection.addAll(overrideCollection);
newCollection.addAll(originalCollection); // Won't add if it's already there.
return newCollection;
}

private <T> T overrideObject(T originalObject, T overrideObject) {
if (overrideObject != null) {
return overrideObject;
}
return originalObject;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.quarkus.smallrye.graphql.deployment;

import java.util.Map;

import io.quarkus.builder.item.SimpleBuildItem;

final class SmallRyeGraphQLIndexBuildItem extends SimpleBuildItem {

private final Map<String, byte[]> modifiedClases;

public SmallRyeGraphQLIndexBuildItem(Map<String, byte[]> modifiedClases) {
this.modifiedClases = modifiedClases;
}

public Map<String, byte[]> getModifiedClases() {
return modifiedClases;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package io.quarkus.smallrye.graphql.deployment;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
Expand All @@ -13,7 +15,7 @@
import java.util.stream.Stream;

import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.Indexer;
import org.jboss.logging.Logger;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
Expand All @@ -38,6 +40,7 @@
import io.quarkus.deployment.builditem.LiveReloadBuildItem;
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.builditem.SystemPropertyBuildItem;
import io.quarkus.deployment.builditem.TransformedClassesBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveHierarchyBuildItem;
Expand Down Expand Up @@ -158,20 +161,48 @@ void registerNativeImageResources(BuildProducer<ServiceProviderBuildItem> servic
.produce(ServiceProviderBuildItem.allProvidersFromClassPath(SmallRyeGraphQLConfigMapping.class.getName()));
}

@BuildStep
SmallRyeGraphQLIndexBuildItem createIndex(TransformedClassesBuildItem transformedClassesBuildItem) {
phillip-kruger marked this conversation as resolved.
Show resolved Hide resolved
Map<String, byte[]> modifiedClasses = new HashMap<>();
Map<Path, Set<TransformedClassesBuildItem.TransformedClass>> transformedClassesByJar = transformedClassesBuildItem
.getTransformedClassesByJar();
for (Map.Entry<Path, Set<TransformedClassesBuildItem.TransformedClass>> transformedClassesByJarEntrySet : transformedClassesByJar
.entrySet()) {

Set<TransformedClassesBuildItem.TransformedClass> transformedClasses = transformedClassesByJarEntrySet.getValue();
for (TransformedClassesBuildItem.TransformedClass transformedClass : transformedClasses) {
modifiedClasses.put(transformedClass.getClassName(), transformedClass.getData());
}
}
return new SmallRyeGraphQLIndexBuildItem(modifiedClasses);
}

@Record(ExecutionTime.STATIC_INIT)
@BuildStep
void buildExecutionService(
BuildProducer<ReflectiveClassBuildItem> reflectiveClassProducer,
BuildProducer<ReflectiveHierarchyBuildItem> reflectiveHierarchyProducer,
BuildProducer<SmallRyeGraphQLInitializedBuildItem> graphQLInitializedProducer,
SmallRyeGraphQLRecorder recorder,
SmallRyeGraphQLIndexBuildItem graphQLIndexBuildItem,
BeanContainerBuildItem beanContainer,
CombinedIndexBuildItem combinedIndex,
SmallRyeGraphQLConfig graphQLConfig) {

IndexView index = combinedIndex.getIndex();
Indexer indexer = new Indexer();
Map<String, byte[]> modifiedClases = graphQLIndexBuildItem.getModifiedClases();

for (Map.Entry<String, byte[]> kv : modifiedClases.entrySet()) {
try (ByteArrayInputStream bais = new ByteArrayInputStream(kv.getValue())) {
indexer.index(bais);
} catch (IOException ex) {
LOG.warn("Could not index [" + kv.getKey() + "] - " + ex.getMessage());
}
}

OverridableIndex overridableIndex = OverridableIndex.create(combinedIndex.getIndex(), indexer.complete());

Schema schema = SchemaBuilder.build(index, graphQLConfig.autoNameStrategy);
Schema schema = SchemaBuilder.build(overridableIndex, graphQLConfig.autoNameStrategy);

RuntimeValue<Boolean> initialized = recorder.createExecutionService(beanContainer.getValue(), schema);
graphQLInitializedProducer.produce(new SmallRyeGraphQLInitializedBuildItem(initialized));
Expand Down
Loading