Skip to content

Commit

Permalink
GH-1473: fixing deserialization of index cache issue with duplicated …
Browse files Browse the repository at this point in the history
…type name attribute

Fixes GH-1473
  • Loading branch information
martinlippert committed Feb 7, 2025
1 parent 6698801 commit 8f6b5a6
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,9 @@ public String toString() {
Gson gson = new Gson();
return gson.toJson(this);
}

public Set<String> getSupertypes() {
return supertypes;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@

/**
* @author Martin Lippert
*
* @deprecated Use IndexCacheOnDiscDeltaBased - this class is no longer maintained and up-to-date with the latest index changes
*/
public class IndexCacheOnDisc implements IndexCache {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,17 +367,6 @@ private <T extends IndexCacheable> Pair<IndexCacheStore<T>, Integer> retrieveSto



public static Gson createGson() {
return new GsonBuilder()
.registerTypeAdapter(DeltaStorage.class, new DeltaStorageAdapter())
.registerTypeAdapter(Bean.class, new BeanJsonAdapter())
.registerTypeAdapter(InjectionPoint.class, new InjectionPointJsonAdapter())
.registerTypeAdapter(IndexCacheStore.class, new IndexCacheStoreAdapter())
.registerTypeAdapter(SpringIndexElement.class, new SpringIndexElementAdapter())
.create();
}


/**
* just keep a md5 hash internally for identifying files to save memory
*/
Expand Down Expand Up @@ -577,6 +566,17 @@ public IndexCacheStore<T> apply(IndexCacheStore<T> store) {
//


public static Gson createGson() {
return new GsonBuilder()
.registerTypeAdapter(DeltaStorage.class, new DeltaStorageAdapter())
.registerTypeAdapter(Bean.class, new BeanJsonAdapter())
.registerTypeAdapter(InjectionPoint.class, new InjectionPointJsonAdapter())
.registerTypeAdapter(IndexCacheStore.class, new IndexCacheStoreAdapter())
.registerTypeAdapter(SpringIndexElement.class, new SpringIndexElementAdapter())
.create();
}


private static class IndexCacheStoreAdapter implements JsonDeserializer<IndexCacheStore<?>> {

@SuppressWarnings({ "rawtypes", "unchecked" })
Expand Down Expand Up @@ -635,7 +635,7 @@ public DeltaStorage<?> deserialize(JsonElement json, Type type, JsonDeserializat
}
}

private static class BeanJsonAdapter implements JsonDeserializer<Bean> {
private static class BeanJsonAdapter implements JsonSerializer<Bean>, JsonDeserializer<Bean> {

@Override
public Bean deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
Expand Down Expand Up @@ -670,6 +670,30 @@ public Bean deserialize(JsonElement json, Type type, JsonDeserializationContext

return bean;
}

@Override
public JsonElement serialize(Bean src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject bean = new JsonObject();

bean.addProperty("name", src.getName());
bean.addProperty("type", src.getType());

bean.add("location", context.serialize(src.getLocation()));
bean.add("injectionPoints", context.serialize(src.getInjectionPoints()));

bean.add("supertypes", context.serialize(src.getSupertypes()));
bean.add("annotations", context.serialize(src.getAnnotations()));

bean.addProperty("isConfiguration", src.isConfiguration());

Type childrenListType = TypeToken.getParameterized(List.class, SpringIndexElement.class).getType();
bean.add("children", context.serialize(src.getChildren(), childrenListType));

bean.addProperty("_internal_node_type", src.getClass().getName());

return bean;
}

}

private static class InjectionPointJsonAdapter implements JsonDeserializer<InjectionPoint> {
Expand All @@ -696,14 +720,14 @@ private static class SpringIndexElementAdapter implements JsonSerializer<SpringI
@Override
public JsonElement serialize(SpringIndexElement element, Type typeOfSrc, JsonSerializationContext context) {
JsonElement elem = context.serialize(element);
elem.getAsJsonObject().addProperty("type", element.getClass().getName());
elem.getAsJsonObject().addProperty("_internal_node_type", element.getClass().getName());
return elem;
}

@Override
public SpringIndexElement deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
String typeName = jsonObject.get("type").getAsString();
String typeName = jsonObject.get("_internal_node_type").getAsString();

try {
return context.deserialize(jsonObject, (Class<?>) Class.forName(typeName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class SpringFactoriesIndexer implements SpringIndexer {

// whenever the implementation of the indexer changes in a way that the stored data in the cache is no longer valid,
// we need to change the generation - this will result in a re-indexing due to no up-to-date cache data being found
private static final String GENERATION = "GEN-10";
private static final String GENERATION = "GEN-11";

private static final String FILE_PATTERN = "**/META-INF/spring/*.factories";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public static enum SCAN_PASS {

// whenever the implementation of the indexer changes in a way that the stored data in the cache is no longer valid,
// we need to change the generation - this will result in a re-indexing due to no up-to-date cache data being found
private static final String GENERATION = "GEN-14";
private static final String GENERATION = "GEN-15";
private static final String INDEX_FILES_TASK_ID = "index-java-source-files-task-";

private static final String SYMBOL_KEY = "symbols";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class SpringIndexerXML implements SpringIndexer {

// whenever the implementation of the indexer changes in a way that the stored data in the cache is no longer valid,
// we need to change the generation - this will result in a re-indexing due to no up-to-date cache data being found
private static final String GENERATION = "GEN-9";
private static final String GENERATION = "GEN-10";

private static final String SYMBOL_KEY = "symbols";
private static final String BEANS_KEY = "beans";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;

Expand Down Expand Up @@ -250,9 +249,9 @@ void testOverallSerializeDeserializeBeans() {
InjectionPoint point2 = new InjectionPoint("point2", "point2-type", locationForDoc1, null);

Bean bean1 = new Bean("beanName1", "beanType", locationForDoc1, new InjectionPoint[] {point1, point2}, Set.of("supertype1", "supertype2"), emptyAnnotations, true);
String serialized = bean1.toString();

Gson gson = IndexCacheOnDiscDeltaBased.createGson();
String serialized = gson.toJson(bean1);
Bean deserializedBean = gson.fromJson(serialized, Bean.class);

assertEquals("beanName1", deserializedBean.getName());
Expand Down Expand Up @@ -301,9 +300,9 @@ void testOverallSerializeDeserializeBeans() {
@Test
void testEmptyInjectionPointsOptimizationWithSerializeDeserializeBeans() {
Bean bean1 = new Bean("beanName1", "beanType", locationForDoc1, emptyInjectionPoints, emptySupertypes, emptyAnnotations, false);
String serialized = bean1.toString();

Gson gson = IndexCacheOnDiscDeltaBased.createGson();
String serialized = gson.toJson(bean1);
Bean deserializedBean = gson.fromJson(serialized, Bean.class);

assertEquals("beanName1", deserializedBean.getName());
Expand Down Expand Up @@ -446,6 +445,30 @@ void testSpringIndexStructurePolymorphicSerialization() {
void testSerializeDeserializeBeansWithChildElements() {

Gson gson = IndexCacheOnDiscDeltaBased.createGson();

Bean bean1 = new Bean("beanName1", "beanType1", locationForDoc1, emptyInjectionPoints, Set.of("supertype1", "supertype2"), emptyAnnotations, false);
Bean bean2 = new Bean("beanName2", "beanType2", locationForDoc1, emptyInjectionPoints, Set.of("supertype3", "supertype4, supertype5"), emptyAnnotations, false);

Bean bean3 = new Bean("beanName3", "beanType1", locationForDoc1, emptyInjectionPoints, Set.of("supertype1", "supertype2"), emptyAnnotations, false);
Bean bean4 = new Bean("beanName4", "beanType2", locationForDoc1, emptyInjectionPoints, Set.of("supertype3", "supertype4, supertype5"), emptyAnnotations, false);

bean1.addChild(bean2);
bean2.addChild(bean3);
bean3.addChild(bean4);

String serialized = gson.toJson(bean1);
Bean newBean = gson.fromJson(serialized, Bean.class);

assertEquals("beanName1", newBean.getName());
assertEquals("beanName2", ((Bean) newBean.getChildren().get(0)).getName());
assertEquals("beanName3", ((Bean) newBean.getChildren().get(0).getChildren().get(0)).getName());
assertEquals("beanName4", ((Bean) newBean.getChildren().get(0).getChildren().get(0).getChildren().get(0)).getName());
}

@Test
void testSerializeDeserializeIndexElementsWithChildElements() {

Gson gson = IndexCacheOnDiscDeltaBased.createGson();

SubType2 childOfChild = new SubType2();
SubType1 child1 = new SubType1();
Expand Down

0 comments on commit 8f6b5a6

Please sign in to comment.