This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git

commit 413db6ec43511eff29a9a915141e16f9c7ce5f7a
Author: wujimin <wuji...@huawei.com>
AuthorDate: Sat Jan 20 01:56:24 2018 +0800

    SCB-266 fix bug: dynamic enum must not determined out of classload
---
 .../common/javassist/JavassistUtils.java           | 22 ++++++-
 .../common/javassist/TestJavassistUtils.java       | 73 ++++++++++++++++++++--
 .../property/StringPropertyConverter.java          | 31 +--------
 3 files changed, 92 insertions(+), 34 deletions(-)

diff --git 
a/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/JavassistUtils.java
 
b/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/JavassistUtils.java
index f75247f..e369174 100644
--- 
a/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/JavassistUtils.java
+++ 
b/common/common-javassist/src/main/java/org/apache/servicecomb/common/javassist/JavassistUtils.java
@@ -20,6 +20,7 @@ package org.apache.servicecomb.common.javassist;
 import static java.util.Locale.ENGLISH;
 
 import java.lang.reflect.Modifier;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.IdentityHashMap;
 import java.util.List;
@@ -30,6 +31,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.util.ClassUtils;
 
 import com.fasterxml.jackson.databind.JavaType;
+import com.google.common.hash.Hashing;
 
 import javassist.CannotCompileException;
 import javassist.ClassPool;
@@ -82,6 +84,25 @@ public final class JavassistUtils {
     return createEnum(null, clsName, values);
   }
 
+  @SuppressWarnings("rawtypes")
+  public static Class<? extends Enum> 
getOrCreateEnumWithPackageName(ClassLoader classLoader, String packageName,
+      List<String> enums) {
+    String strEnums = enums.toString();
+    String enumClsName =
+        packageName + ".Enum_" + Hashing.sha256().hashString(strEnums, 
StandardCharsets.UTF_8).toString();
+    return JavassistUtils.getOrCreateEnumWithClassName(classLoader, 
enumClsName, enums);
+  }
+
+  @SuppressWarnings({"rawtypes", "unchecked"})
+  public static synchronized Class<? extends Enum> 
getOrCreateEnumWithClassName(ClassLoader classLoader, String clsName,
+      List<String> values) {
+    try {
+      return (Class<? extends Enum>) classLoader.loadClass(clsName);
+    } catch (ClassNotFoundException e) {
+      return createEnum(classLoader, clsName, values);
+    }
+  }
+
   @SuppressWarnings({"rawtypes", "unchecked"})
   public static Class<? extends Enum> createEnum(ClassLoader classLoader, 
String clsName, List<String> values) {
     if (values == null || values.size() == 0) {
@@ -148,7 +169,6 @@ public final class JavassistUtils {
       if (config.isIntf()) {
         ctClass = classPool.makeInterface(config.getClassName());
       } else {
-
         ctClass = classPool.makeClass(config.getClassName());
       }
     }
diff --git 
a/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestJavassistUtils.java
 
b/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestJavassistUtils.java
index f7f11bb..73c4c7f 100644
--- 
a/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestJavassistUtils.java
+++ 
b/common/common-javassist/src/test/java/org/apache/servicecomb/common/javassist/TestJavassistUtils.java
@@ -18,18 +18,24 @@
 package org.apache.servicecomb.common.javassist;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.ws.rs.core.Response.Status;
+
 import org.apache.servicecomb.foundation.common.utils.ReflectUtils;
 import org.junit.Assert;
 import org.junit.Test;
 
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.type.TypeFactory;
+import com.google.common.hash.Hashing;
 
 import javassist.ClassPool;
 import mockit.Deencapsulation;
@@ -161,13 +167,70 @@ public class TestJavassistUtils {
   }
 
   @Test
+  public void getOrCreateEnumWithClassName_get() {
+    Class<?> cls = Status.class;
+
+    Assert.assertSame(cls,
+        
JavassistUtils.getOrCreateEnumWithClassName(Thread.currentThread().getContextClassLoader(),
+            Status.class.getName(),
+            null));
+  }
+
+  @Test
+  public void getOrCreateEnumWithClassName_create()
+      throws NoSuchMethodException, IllegalAccessException, 
InvocationTargetException {
+    String name = "cse.ut.EnumAbc";
+    Assert.assertNull(ClassPool.getDefault().getOrNull(name));
+
+    @SuppressWarnings("rawtypes")
+    Class<? extends Enum> cls =
+        JavassistUtils
+            
.getOrCreateEnumWithClassName(Thread.currentThread().getContextClassLoader(),
+                name,
+                Arrays.asList("a", "b"));
+    checkEnum(name, cls);
+  }
+
+  @Test
+  public void getOrCreateEnumWithPackageName()
+      throws NoSuchMethodException, IllegalAccessException, 
InvocationTargetException {
+    List<String> enums = Arrays.asList("a", "b");
+    String packageName = "cse.ut";
+    String clsName =
+        packageName + ".Enum_" + Hashing.sha256().hashString(enums.toString(), 
StandardCharsets.UTF_8).toString();
+    Assert.assertNull(ClassPool.getDefault().getOrNull(clsName));
+
+    @SuppressWarnings("rawtypes")
+    Class<? extends Enum> cls =
+        JavassistUtils
+            
.getOrCreateEnumWithPackageName(Thread.currentThread().getContextClassLoader(),
+                packageName,
+                Arrays.asList("a", "b"));
+
+    checkEnum(clsName, cls);
+    Assert.assertSame(cls,
+        JavassistUtils
+            
.getOrCreateEnumWithPackageName(Thread.currentThread().getContextClassLoader(),
+                packageName,
+                Arrays.asList("a", "b")));
+
+  }
+
+  @Test
   public void testEnum() throws Exception {
+    String name = "cse.ut.EnumAbc2";
     @SuppressWarnings("rawtypes")
-    Class<? extends Enum> cls = JavassistUtils.createEnum("cse.ut.EnumAbc", 
"a", "b");
+    Class<? extends Enum> cls = JavassistUtils.createEnum(name, "a", "b");
+    checkEnum(name, cls);
+  }
+
+  @SuppressWarnings("rawtypes")
+  protected void checkEnum(String expectName, Class<? extends Enum> cls)
+      throws NoSuchMethodException, IllegalAccessException, 
InvocationTargetException {
     Method method = cls.getMethod("values");
     Enum<?>[] values = (Enum<?>[]) method.invoke(null);
 
-    Assert.assertEquals("cse.ut.EnumAbc", cls.getName());
+    Assert.assertEquals(expectName, cls.getName());
     Assert.assertEquals(2, values.length);
     Assert.assertEquals("a", values[0].name());
     Assert.assertEquals(0, values[0].ordinal());
@@ -192,8 +255,10 @@ public class TestJavassistUtils {
 
   @Test
   public void managerClassPool() {
-    ClassLoader classLoader1 = new ClassLoader() { };
-    ClassLoader classLoader2 = new ClassLoader() { };
+    ClassLoader classLoader1 = new ClassLoader() {
+    };
+    ClassLoader classLoader2 = new ClassLoader() {
+    };
 
     ClassPool p1 = Deencapsulation.invoke(JavassistUtils.class, 
"getOrCreateClassPool", classLoader1);
     ClassPool p2 = Deencapsulation.invoke(JavassistUtils.class, 
"getOrCreateClassPool", classLoader2);
diff --git 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/property/StringPropertyConverter.java
 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/property/StringPropertyConverter.java
index a4372a1..b34272c 100644
--- 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/property/StringPropertyConverter.java
+++ 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/converter/property/StringPropertyConverter.java
@@ -17,9 +17,7 @@
 
 package org.apache.servicecomb.swagger.converter.property;
 
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.servicecomb.common.javassist.JavassistUtils;
 import org.apache.servicecomb.swagger.converter.ConverterMgr;
@@ -31,32 +29,6 @@ import io.swagger.models.Swagger;
 import io.swagger.models.properties.StringProperty;
 
 public class StringPropertyConverter extends AbstractPropertyConverter {
-  // 用于生成唯一的enum名称
-  // key为enum names, value为enum cls javaType
-  private static Map<String, JavaType> enumMap = new HashMap<>();
-
-  private static final Object LOCK = new Object();
-
-  // 转换并创建enum是小概率事件,没必要double check
-  private static JavaType getOrCreateEnumByNames(ClassLoader classLoader, 
String packageName, List<String> enums) {
-    String strEnums = enums.toString();
-
-    synchronized (LOCK) {
-      JavaType javaType = enumMap.get(strEnums);
-      if (javaType != null) {
-        return javaType;
-      }
-
-      String enumClsName = packageName + ".Enum" + enumMap.size();
-      @SuppressWarnings("rawtypes")
-      Class<? extends Enum> enumCls = JavassistUtils.createEnum(classLoader, 
enumClsName, enums);
-      javaType = TypeFactory.defaultInstance().constructType(enumCls);
-      enumMap.put(strEnums, javaType);
-
-      return javaType;
-    }
-  }
-
   public static JavaType findJavaType(ClassLoader classLoader, String 
packageName, Swagger swagger, String type,
       String format, List<String> enums) {
     if (!isEnum(enums)) {
@@ -64,7 +36,8 @@ public class StringPropertyConverter extends 
AbstractPropertyConverter {
     }
 
     // enum,且需要动态生成class
-    return getOrCreateEnumByNames(classLoader, packageName, enums);
+    Class<?> enumCls = 
JavassistUtils.getOrCreateEnumWithPackageName(classLoader, packageName, enums);
+    return TypeFactory.defaultInstance().constructType(enumCls);
   }
 
   public static boolean isEnum(StringProperty stringProperty) {

-- 
To stop receiving notification emails like this one, please contact
"commits@servicecomb.apache.org" <commits@servicecomb.apache.org>.

Reply via email to