GH-1473: fixing deserialization of index cache issue with duplicated type name attribute
Fixes GH-1473
This commit is contained in:
@@ -98,5 +98,9 @@ public class Bean extends AbstractSpringIndexElement {
|
||||
Gson gson = new Gson();
|
||||
return gson.toJson(this);
|
||||
}
|
||||
|
||||
public Set<String> getSupertypes() {
|
||||
return supertypes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ import com.google.gson.stream.JsonReader;
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
|
||||
|
||||
@@ -367,17 +367,6 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
|
||||
|
||||
|
||||
|
||||
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
|
||||
*/
|
||||
@@ -577,6 +566,17 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
|
||||
//
|
||||
|
||||
|
||||
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" })
|
||||
@@ -635,7 +635,7 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -670,6 +670,30 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
|
||||
|
||||
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> {
|
||||
@@ -696,14 +720,14 @@ public class IndexCacheOnDiscDeltaBased implements IndexCache {
|
||||
@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));
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ public class SpringIndexerJava 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-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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -13,7 +13,6 @@ package org.springframework.ide.vscode.boot.index.test;
|
||||
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;
|
||||
|
||||
@@ -250,9 +249,9 @@ public class SpringMetamodelIndexTest {
|
||||
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());
|
||||
@@ -301,9 +300,9 @@ public class SpringMetamodelIndexTest {
|
||||
@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());
|
||||
@@ -446,6 +445,30 @@ public class SpringMetamodelIndexTest {
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user