Skip to content

Commit

Permalink
fix: resolve ClassCastException when supporting map type serializatio…
Browse files Browse the repository at this point in the history
…n under fastutil package (#307)

fix: resolve ClassCastException when supporting map type serialization under fastutil package
  • Loading branch information
DanLi39 authored Oct 24, 2023
1 parent d99ad56 commit 2176259
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 8 deletions.
6 changes: 6 additions & 0 deletions arex-instrumentation-foundation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return getImplType(getImplClassPrefix(rawClassName, 4), "ArrayList");
}
if (rawClassName.endsWith(MAP_NAME)) {
return getImplType(getImplClassPrefix(rawClassName, 3), "OpenHashMap");
return FastUtilMapTypeSerializer.getAdapter(type);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.arex.foundation.serializer.custom;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import io.arex.agent.bootstrap.model.ParameterizedTypeImpl;
import io.arex.inst.runtime.log.LogManager;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

public class FastUtilMapTypeSerializer implements JsonDeserializer<Map<Object, Object>> {

private static final String IMPL_MAP_SUFFIX = "OpenHashMap";
private static final GsonBuilder GSON_BUILDER = new GsonBuilder().enableComplexMapKeySerialization();
private static final Gson GSON = GSON_BUILDER.create();

public Map<Object, Object> deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) {
try {
if (type instanceof ParameterizedType) {
final String implName = getImplClassName(type);
final Class<?> implClass = Thread.currentThread().getContextClassLoader().loadClass(implName);
final ParameterizedTypeImpl recreateType = ParameterizedTypeImpl.make(implClass,
((ParameterizedType) type).getActualTypeArguments(), ((ParameterizedType) type).getOwnerType());
return GSON.fromJson(jsonElement, recreateType);
}
return null;
} catch (Exception e) {
LogManager.warn("FastUtilMapTypeSerialzer.deserialize", e);
return null;
}
}

public static <T> TypeAdapter<T> getAdapter(final TypeToken<T> type) {
return GSON_BUILDER.registerTypeAdapter(type.getRawType(), new FastUtilMapTypeSerializer()).create()
.getAdapter(type);
}

private String getImplClassName(Type type) {
final String rawClassName = ((ParameterizedType) type).getRawType().getTypeName();
final String prefix = rawClassName.substring(0, rawClassName.length() - 3);
return prefix + IMPL_MAP_SUFFIX;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ void deserializeType() throws Throwable {
@Test
void testFastUtil() throws Throwable {
final TestType testType = FastUtilAdapterFactoryTest.getTestType();
testType.setObject2DoubleMap(null);
testType.setDoubleRangeObject2DoubleMap(null);
final String jackJson = JacksonSerializer.INSTANCE.serialize(testType);
final TestType deserializeJackTestType = JacksonSerializer.INSTANCE.deserialize(jackJson, TestType.class);
assertNotNull(deserializeJackTestType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,49 @@

import static org.junit.jupiter.api.Assertions.*;

import com.google.common.reflect.TypeToken;
import io.arex.agent.bootstrap.util.StringUtil;
import io.arex.foundation.serializer.GsonSerializer;
import io.arex.foundation.serializer.ProtoJsonSerializer;
import io.arex.foundation.serializer.ProtoTest.HelloProtoRequestType;
import it.unimi.dsi.fastutil.floats.FloatArrayList;
import it.unimi.dsi.fastutil.floats.FloatList;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import java.util.HashMap;
import it.unimi.dsi.fastutil.objects.Object2DoubleArrayMap;
import it.unimi.dsi.fastutil.objects.Object2DoubleMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.Assertions;
import org.apache.commons.lang.math.DoubleRange;
import org.junit.jupiter.api.Test;

public class FastUtilAdapterFactoryTest {

public static TestType getTestType() {
final TestType testType = new TestType(1, "test");

final IntOpenHashSet intOpenHashSet = new IntOpenHashSet();
intOpenHashSet.add(2);
testType.setIntSet(intOpenHashSet);

final FloatArrayList floats = new FloatArrayList();
floats.add(1.0f);
testType.setFloats(floats);

final LongLinkedOpenHashSet linkedOpenHashSet = new LongLinkedOpenHashSet();
linkedOpenHashSet.add(3L);
testType.setLongSet(linkedOpenHashSet);

final HashSet<Integer> hashSet = new HashSet<>();
hashSet.add(1);
testType.setSet(new Set[]{hashSet});

final Object2DoubleMap<DoubleRange> object2DoubleMap = new Object2DoubleArrayMap<>(2);
final DoubleRange doubleRange1 = new DoubleRange(1, 3);
final DoubleRange doubleRange2 = new DoubleRange(6, 9);
object2DoubleMap.put(doubleRange1, 2);
object2DoubleMap.put(doubleRange2, 8);
testType.setObject2DoubleMap(object2DoubleMap);
testType.setDoubleRangeObject2DoubleMap(object2DoubleMap);

return testType;
}

Expand All @@ -47,12 +57,15 @@ void testFastUtilAdapter() throws Throwable {
}

public static class TestType {

private int id;
private String name;
private IntSet intSet;
private FloatList floats;
private LongSet longSet;
private Set<Integer>[] set;
private Object2DoubleMap object2DoubleMap;
private Object2DoubleMap<DoubleRange> doubleRangeObject2DoubleMap;

public TestType() {
}
Expand Down Expand Up @@ -109,5 +122,22 @@ public Set<Integer>[] getSet() {
public void setSet(Set<Integer>[] set) {
this.set = set;
}

public Object2DoubleMap getObject2DoubleMap() {
return object2DoubleMap;
}

public void setObject2DoubleMap(Object2DoubleMap object2DoubleMap) {
this.object2DoubleMap = object2DoubleMap;
}

public Object2DoubleMap<DoubleRange> getdoubleRangeObject2DoubleMap() {
return doubleRangeObject2DoubleMap;
}

public void setDoubleRangeObject2DoubleMap(
Object2DoubleMap<DoubleRange> doubleRangeObject2DoubleMap) {
this.doubleRangeObject2DoubleMap = doubleRangeObject2DoubleMap;
}
}
}

0 comments on commit 2176259

Please sign in to comment.