This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.1 by this push:
new 9a80b03b17 Enhance json util check (#11501)
9a80b03b17 is described below
commit 9a80b03b175b19d6f3b98b8d99cdbdc1644a29aa
Author: Albumen Kevin <[email protected]>
AuthorDate: Tue Feb 14 15:14:39 2023 +0800
Enhance json util check (#11501)
---
.../dubbo/common/json/impl/FastJsonImpl.java | 22 ++++--
.../apache/dubbo/common/json/impl/GsonImpl.java | 22 ++++--
.../dubbo/common/json/impl/FastJsonImplTest.java | 65 ++++++++++++++++
.../dubbo/common/json/impl/GsonImplTest.java | 82 ++++++++++++++++++++
.../apache/dubbo/common/utils/JsonUtilsTest.java | 90 ++++++++++++++--------
5 files changed, 236 insertions(+), 45 deletions(-)
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java
b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java
index e5b440c044..5cc318b21e 100644
---
a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java
+++
b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java
@@ -16,20 +16,30 @@
*/
package org.apache.dubbo.common.json.impl;
-import org.apache.dubbo.common.utils.ClassUtils;
-
-import com.alibaba.fastjson.serializer.SerializerFeature;
-
import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import com.alibaba.fastjson.serializer.SerializerFeature;
public class FastJsonImpl extends AbstractJSONImpl {
@Override
public boolean isSupport() {
try {
- Class<?> aClass = ClassUtils.forName("com.alibaba.fastjson.JSON");
- return aClass != null;
+ Map<String, String> map = new HashMap<>();
+ map.put("fastjson", "test");
+ if (!CollectionUtils.mapEquals(map, toJavaObject(toJson(map),
Map.class))) {
+ return false;
+ }
+
+ List<String> list = new LinkedList<>();
+ list.add("fastjson");
+ return CollectionUtils.equals(list, toJavaList(toJson(list),
String.class));
} catch (Throwable t) {
return false;
}
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java
b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java
index cbd76fe1b3..fd8cb40f82 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java
@@ -16,14 +16,17 @@
*/
package org.apache.dubbo.common.json.impl;
-import org.apache.dubbo.common.utils.ClassUtils;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.dubbo.common.utils.CollectionUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
-import java.lang.reflect.Type;
-import java.util.List;
-
public class GsonImpl extends AbstractJSONImpl {
// weak reference of com.google.gson.Gson, prevent throw exception when
init
private volatile Object gsonCache = null;
@@ -31,8 +34,15 @@ public class GsonImpl extends AbstractJSONImpl {
@Override
public boolean isSupport() {
try {
- Class<?> aClass = ClassUtils.forName("com.google.gson.Gson");
- return aClass != null;
+ Map<String, String> map = new HashMap<>();
+ map.put("gson", "test");
+ if (!CollectionUtils.mapEquals(map, toJavaObject(toJson(map),
Map.class))) {
+ return false;
+ }
+
+ List<String> list = new LinkedList<>();
+ list.add("gson");
+ return CollectionUtils.equals(list, toJavaList(toJson(list),
String.class));
} catch (Throwable t) {
return false;
}
diff --git
a/dubbo-common/src/test/java/org/apache/dubbo/common/json/impl/FastJsonImplTest.java
b/dubbo-common/src/test/java/org/apache/dubbo/common/json/impl/FastJsonImplTest.java
new file mode 100644
index 0000000000..a3fd701c97
--- /dev/null
+++
b/dubbo-common/src/test/java/org/apache/dubbo/common/json/impl/FastJsonImplTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.json.impl;
+
+import java.lang.reflect.Type;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import com.alibaba.fastjson.JSON;
+
+import static org.mockito.Answers.CALLS_REAL_METHODS;
+
+class FastJsonImplTest {
+ private static MockedStatic<JSON> fastjsonMock;
+
+ @BeforeAll
+ static void setup() {
+ fastjsonMock = Mockito.mockStatic(JSON.class, CALLS_REAL_METHODS);
+ }
+
+ @AfterAll
+ static void teardown() {
+ fastjsonMock.close();
+ }
+
+ @Test
+ void testSupported() {
+ Assertions.assertTrue(new FastJsonImpl().isSupport());
+
+ fastjsonMock.when(() -> JSON.toJSONString(Mockito.any(),
Mockito.any())).thenThrow(new RuntimeException());
+ Assertions.assertFalse(new FastJsonImpl().isSupport());
+ fastjsonMock.reset();
+
+ fastjsonMock.when(() -> JSON.toJSONString(Mockito.any(),
Mockito.any())).thenReturn(null);
+ Assertions.assertFalse(new FastJsonImpl().isSupport());
+ fastjsonMock.reset();
+
+ fastjsonMock.when(() -> JSON.parseObject((String) Mockito.any(),
(Type) Mockito.any())).thenReturn(null);
+ Assertions.assertFalse(new FastJsonImpl().isSupport());
+ fastjsonMock.reset();
+
+ fastjsonMock.when(() -> JSON.parseArray(Mockito.any(), (Class)
Mockito.any())).thenReturn(null);
+ Assertions.assertFalse(new FastJsonImpl().isSupport());
+ fastjsonMock.reset();
+ }
+}
diff --git
a/dubbo-common/src/test/java/org/apache/dubbo/common/json/impl/GsonImplTest.java
b/dubbo-common/src/test/java/org/apache/dubbo/common/json/impl/GsonImplTest.java
new file mode 100644
index 0000000000..3ea55a76ce
--- /dev/null
+++
b/dubbo-common/src/test/java/org/apache/dubbo/common/json/impl/GsonImplTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.json.impl;
+
+import java.lang.reflect.Type;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedConstruction;
+import org.mockito.Mockito;
+
+import com.google.gson.Gson;
+
+public class GsonImplTest {
+
+ private static Gson gson = new Gson();
+ private static AtomicReference<Gson> gsonReference = new
AtomicReference<>();
+ private static MockedConstruction<Gson> gsonMock;
+ private static AtomicReference<Consumer<Gson>> gsonInit = new
AtomicReference<>();
+
+ @BeforeAll
+ static void setup() {
+ gsonMock = Mockito.mockConstruction(Gson.class,
+ (mock, context) -> {
+ gsonReference.set(mock);
+ Mockito.when(mock.toJson((Object)
Mockito.any())).thenAnswer(invocation -> gson.toJson((Object)
invocation.getArgument(0)));
+ Mockito.when(mock.fromJson(Mockito.anyString(), (Type)
Mockito.any())).thenAnswer(invocation -> gson.fromJson((String)
invocation.getArgument(0), (Type) invocation.getArgument(1)));
+ Consumer<Gson> gsonConsumer = gsonInit.get();
+ if (gsonConsumer != null) {
+ gsonConsumer.accept(mock);
+ }
+ });
+ }
+
+ @AfterAll
+ static void teardown() {
+ gsonMock.close();
+ }
+
+ @Test
+ void testSupported() {
+ Assertions.assertTrue(new GsonImpl().isSupport());
+
+ gsonInit.set(g -> Mockito.when(g.toJson((Object)
Mockito.any())).thenThrow(new RuntimeException()));
+ Assertions.assertFalse(new GsonImpl().isSupport());
+ gsonInit.set(null);
+
+ gsonInit.set(g -> Mockito.when(g.fromJson(Mockito.anyString(), (Type)
Mockito.any())).thenThrow(new RuntimeException()));
+ Assertions.assertFalse(new GsonImpl().isSupport());
+ gsonInit.set(null);
+
+ gsonInit.set(g -> Mockito.when(g.toJson((Object)
Mockito.any())).thenReturn(null));
+ Assertions.assertFalse(new GsonImpl().isSupport());
+ gsonInit.set(null);
+
+ gsonInit.set(g -> Mockito.when(g.fromJson(Mockito.anyString(), (Type)
Mockito.any())).thenReturn(null));
+ Assertions.assertFalse(new GsonImpl().isSupport());
+ gsonInit.set(null);
+
+ gsonInit.set(g -> Mockito.when(g.fromJson(Mockito.eq("[\"gson\"]"),
(Type) Mockito.any())).thenReturn(null));
+ Assertions.assertFalse(new GsonImpl().isSupport());
+ gsonInit.set(null);
+ }
+}
diff --git
a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java
b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java
index 3757082ac8..d15082ed6e 100644
---
a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java
+++
b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java
@@ -16,20 +16,57 @@
*/
package org.apache.dubbo.common.utils;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+
import org.apache.dubbo.common.json.impl.FastJsonImpl;
import org.apache.dubbo.common.json.impl.GsonImpl;
-
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.mockito.MockedConstruction;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import com.alibaba.fastjson.JSON;
+import com.google.gson.Gson;
+
+import static org.mockito.Answers.CALLS_REAL_METHODS;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
class JsonUtilsTest {
+ private static Gson gson = new Gson();
+ private static MockedStatic<JSON> fastjsonMock;
+ private static AtomicReference<Gson> gsonReference = new
AtomicReference<>();
+ private static MockedConstruction<Gson> gsonMock;
+ private static AtomicReference<Consumer<Gson>> gsonInit = new
AtomicReference<>();
+
+ @BeforeAll
+ static void setup() {
+ fastjsonMock = Mockito.mockStatic(JSON.class, CALLS_REAL_METHODS);
+ gsonMock = Mockito.mockConstruction(Gson.class,
+ (mock, context) -> {
+ gsonReference.set(mock);
+ Mockito.when(mock.toJson((Object)
Mockito.any())).thenAnswer(invocation -> gson.toJson((Object)
invocation.getArgument(0)));
+ Mockito.when(mock.fromJson(Mockito.anyString(), (Type)
Mockito.any())).thenAnswer(invocation -> gson.fromJson((String)
invocation.getArgument(0), (Type) invocation.getArgument(1)));
+ Consumer<Gson> gsonConsumer = gsonInit.get();
+ if (gsonConsumer != null) {
+ gsonConsumer.accept(mock);
+ }
+ });
+ }
+
+ @AfterAll
+ static void teardown() {
+ fastjsonMock.close();
+ gsonMock.close();
+ }
+
@Test
void testGetJson1() {
Assertions.assertNotNull(JsonUtils.getJson());
@@ -62,77 +99,64 @@ class JsonUtilsTest {
@Test
void testGetJson2() {
- ClassLoader originClassLoader =
Thread.currentThread().getContextClassLoader();
- AtomicReference<List<String>> removedPackages = new
AtomicReference<>(Collections.emptyList());
- ClassLoader newClassLoader = new ClassLoader(originClassLoader) {
- @Override
- public Class<?> loadClass(String name) throws
ClassNotFoundException {
- for (String removedPackage : removedPackages.get()) {
- if (name.startsWith(removedPackage)) {
- throw new ClassNotFoundException("Test");
- }
- }
- return super.loadClass(name);
- }
- };
- Thread.currentThread().setContextClassLoader(newClassLoader);
-
// default use fastjson
JsonUtils.setJson(null);
- removedPackages.set(Collections.emptyList());
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());
// prefer use fastjson
JsonUtils.setJson(null);
- removedPackages.set(Collections.emptyList());
System.setProperty("dubbo.json-framework.prefer", "fastjson");
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());
System.clearProperty("dubbo.json-framework.prefer");
// prefer use gson
JsonUtils.setJson(null);
- removedPackages.set(Collections.emptyList());
System.setProperty("dubbo.json-framework.prefer", "gson");
Assertions.assertInstanceOf(GsonImpl.class, JsonUtils.getJson());
System.clearProperty("dubbo.json-framework.prefer");
// prefer use not found
JsonUtils.setJson(null);
- removedPackages.set(Collections.emptyList());
System.setProperty("dubbo.json-framework.prefer", "notfound");
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());
System.clearProperty("dubbo.json-framework.prefer");
JsonUtils.setJson(null);
// TCCL not found fastjson
- removedPackages.set(Collections.singletonList("com.alibaba.fastjson"));
+ fastjsonMock.when(() -> JSON.toJSONString(Mockito.any(),
Mockito.any())).thenThrow(new RuntimeException());
Assertions.assertInstanceOf(GsonImpl.class, JsonUtils.getJson());
+ fastjsonMock.reset();
JsonUtils.setJson(null);
// TCCL not found gson
- removedPackages.set(Collections.singletonList("com.google.gson"));
+ gsonInit.set(mock -> Mockito.reset(mock));
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());
+ gsonInit.set(null);
JsonUtils.setJson(null);
// TCCL not found fastjson, prefer use fastjson
- removedPackages.set(Collections.singletonList("com.alibaba.fastjson"));
+ fastjsonMock.when(() -> JSON.toJSONString(Mockito.any(),
Mockito.any())).thenThrow(new RuntimeException());
System.setProperty("dubbo.json-framework.prefer", "fastjson");
Assertions.assertInstanceOf(GsonImpl.class, JsonUtils.getJson());
System.clearProperty("dubbo.json-framework.prefer");
+ fastjsonMock.reset();
JsonUtils.setJson(null);
// TCCL not found gson, prefer use gson
- removedPackages.set(Collections.singletonList("com.google.gson"));
+ gsonInit.set(mock -> Mockito.reset(mock));
System.setProperty("dubbo.json-framework.prefer", "gson");
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());
System.clearProperty("dubbo.json-framework.prefer");
+ gsonInit.set(null);
JsonUtils.setJson(null);
// TCCL not found fastjson, gson
- removedPackages.set(Arrays.asList("com.alibaba.fastjson",
"com.google.gson"));
+ fastjsonMock.when(() -> JSON.toJSONString((Object) Mockito.any(),
Mockito.any())).thenThrow(new RuntimeException());
+ gsonInit.set(mock -> Mockito.reset(mock));
Assertions.assertThrows(IllegalStateException.class,
JsonUtils::getJson);
+ gsonInit.set(null);
+ fastjsonMock.reset();
- Thread.currentThread().setContextClassLoader(originClassLoader);
JsonUtils.setJson(null);
}
-}
\ No newline at end of file
+}