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
+}

Reply via email to