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

iluo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git


The following commit(s) were added to refs/heads/master by this push:
     new caac0b5  refactor javassist compiler: extract class CtClassBuilder 
(#3424)
caac0b5 is described below

commit caac0b573c8f87d0147983c149d5f7d96db2b20c
Author: wanghbxxxx <[email protected]>
AuthorDate: Mon Feb 11 16:44:41 2019 +0800

    refactor javassist compiler: extract class CtClassBuilder (#3424)
    
    * refactor JavassistCompiler
    
    * rename variable names
    
    * reformat code
    
    * refactor: prepend modifier of constructor, field and method outside the
    JavassistClassInfo
    
    * add null for ClassUtils.getSimpleClassName
    
    * rename JavassistClassInfo to CtClassBuilder
---
 .../dubbo/common/compiler/support/ClassUtils.java  |  12 ++
 .../common/compiler/support/CtClassBuilder.java    | 174 +++++++++++++++++++++
 .../common/compiler/support/JavassistCompiler.java |  97 ++++--------
 .../common/compiler/support/ClassUtilsTest.java    |   7 +
 4 files changed, 222 insertions(+), 68 deletions(-)

diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java
index 5d3cdad..365cb7f 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java
@@ -431,5 +431,17 @@ public class ClassUtils {
         }
         return map;
     }
+    
+    /**
+     * get simple class name from qualified class name
+     */
+    public static String getSimpleClassName(String qualifiedName) {
+        if (null == qualifiedName) {
+            return null;
+        }
+        
+        int i = qualifiedName.lastIndexOf('.');
+        return i < 0 ? qualifiedName : qualifiedName.substring(i + 1);
+    }
 
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java
new file mode 100644
index 0000000..0dc8f88
--- /dev/null
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java
@@ -0,0 +1,174 @@
+/*
+ * 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.compiler.support;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtNewConstructor;
+import javassist.CtNewMethod;
+import javassist.LoaderClassPath;
+import javassist.NotFoundException;
+
+/**
+ * CtClassBuilder is builder for CtClass
+ * <p>
+ * contains all the information, including:
+ * <p>
+ * class name, imported packages, super class name, implemented interfaces, 
constructors, fields, methods.
+ */
+public class CtClassBuilder {
+
+    private String className;
+
+    private String superClassName = "java.lang.Object";
+
+    private List<String> imports = new ArrayList<>();
+
+    private Map<String, String> fullNames = new HashMap<>();
+
+    private List<String> ifaces = new ArrayList<>();
+
+    private List<String> constructors = new ArrayList<>();
+
+    private List<String> fields = new ArrayList<>();
+
+    private List<String> methods = new ArrayList<>();
+
+    public String getClassName() {
+        return className;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public String getSuperClassName() {
+        return superClassName;
+    }
+
+    public void setSuperClassName(String superClassName) {
+        this.superClassName = getQualifiedClassName(superClassName);
+    }
+
+    public List<String> getImports() {
+        return imports;
+    }
+
+    public void addImports(String pkg) {
+        int pi = pkg.lastIndexOf('.');
+        if (pi > 0) {
+            String pkgName = pkg.substring(0, pi);
+            this.imports.add(pkgName);
+            if (!pkg.endsWith(".*")) {
+                fullNames.put(pkg.substring(pi + 1), pkg);
+            }
+        }
+    }
+
+    public List<String> getInterfaces() {
+        return ifaces;
+    }
+
+    public void addInterface(String iface) {
+        this.ifaces.add(getQualifiedClassName(iface));
+    }
+
+    public List<String> getConstructors() {
+        return constructors;
+    }
+
+    public void addConstructor(String constructor) {
+        this.constructors.add(constructor);
+    }
+
+    public List<String> getFields() {
+        return fields;
+    }
+
+    public void addField(String field) {
+        this.fields.add(field);
+    }
+
+    public List<String> getMethods() {
+        return methods;
+    }
+
+    public void addMethod(String method) {
+        this.methods.add(method);
+    }
+
+    /**
+     * get full qualified class name
+     * 
+     * @param className super class name, maybe qualified or not
+     */
+    protected String getQualifiedClassName(String className) {
+        if (className.contains(".")) {
+            return className;
+        }
+
+        if (fullNames.containsKey(className)) {
+            return fullNames.get(className);
+        }
+
+        return ClassUtils.forName(imports.toArray(new String[0]), 
className).getName();
+    }
+
+    /**
+     * build CtClass object
+     */
+    public CtClass build(ClassLoader classLoader) throws NotFoundException, 
CannotCompileException {
+        ClassPool pool = new ClassPool(true);
+        pool.appendClassPath(new LoaderClassPath(classLoader));
+        
+        // create class
+        CtClass ctClass = pool.makeClass(className, pool.get(superClassName));
+
+        // add imported packages
+        imports.stream().forEach(pool::importPackage);
+
+        // add implemented interfaces
+        for (String iface : ifaces) {
+            ctClass.addInterface(pool.get(iface));
+        }
+
+        // add constructors
+        for (String constructor : constructors) {
+            ctClass.addConstructor(CtNewConstructor.make(constructor, 
ctClass));
+        }
+
+        // add fields
+        for (String field : fields) {
+            ctClass.addField(CtField.make(field, ctClass));
+        }
+
+        // add methods
+        for (String method : methods) {
+            ctClass.addMethod(CtNewMethod.make(method, ctClass));
+        }
+
+        return ctClass;
+    }
+
+}
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java
index 5beb8e4..11f76b1 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java
@@ -18,17 +18,9 @@ package org.apache.dubbo.common.compiler.support;
 
 import org.apache.dubbo.common.utils.ClassHelper;
 
-import javassist.ClassPool;
 import javassist.CtClass;
-import javassist.CtField;
-import javassist.CtNewConstructor;
-import javassist.CtNewMethod;
-import javassist.LoaderClassPath;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.Arrays;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -49,77 +41,46 @@ public class JavassistCompiler extends AbstractCompiler {
 
     @Override
     public Class<?> doCompile(String name, String source) throws Throwable {
-        int i = name.lastIndexOf('.');
-        String className = i < 0 ? name : name.substring(i + 1);
-        ClassPool pool = new ClassPool(true);
-        pool.appendClassPath(new 
LoaderClassPath(ClassHelper.getCallerClassLoader(getClass())));
+        CtClassBuilder builder = new CtClassBuilder();
+        builder.setClassName(name);
+
+        // process imported classes
         Matcher matcher = IMPORT_PATTERN.matcher(source);
-        List<String> importPackages = new ArrayList<String>();
-        Map<String, String> fullNames = new HashMap<String, String>();
         while (matcher.find()) {
-            String pkg = matcher.group(1);
-            if (pkg.endsWith(".*")) {
-                String pkgName = pkg.substring(0, pkg.length() - 2);
-                pool.importPackage(pkgName);
-                importPackages.add(pkgName);
-            } else {
-                int pi = pkg.lastIndexOf('.');
-                if (pi > 0) {
-                    String pkgName = pkg.substring(0, pi);
-                    pool.importPackage(pkgName);
-                    importPackages.add(pkgName);
-                    fullNames.put(pkg.substring(pi + 1), pkg);
-                }
-            }
+            builder.addImports(matcher.group(1).trim());
         }
-        String[] packages = importPackages.toArray(new String[0]);
+        
+        // process extended super class
         matcher = EXTENDS_PATTERN.matcher(source);
-        CtClass cls;
         if (matcher.find()) {
-            String extend = matcher.group(1).trim();
-            String extendClass;
-            if (extend.contains(".")) {
-                extendClass = extend;
-            } else if (fullNames.containsKey(extend)) {
-                extendClass = fullNames.get(extend);
-            } else {
-                extendClass = ClassUtils.forName(packages, extend).getName();
-            }
-            cls = pool.makeClass(name, pool.get(extendClass));
-        } else {
-            cls = pool.makeClass(name);
+            builder.setSuperClassName(matcher.group(1).trim());
         }
+        
+        // process implemented interfaces
         matcher = IMPLEMENTS_PATTERN.matcher(source);
         if (matcher.find()) {
             String[] ifaces = matcher.group(1).trim().split("\\,");
-            for (String iface : ifaces) {
-                iface = iface.trim();
-                String ifaceClass;
-                if (iface.contains(".")) {
-                    ifaceClass = iface;
-                } else if (fullNames.containsKey(iface)) {
-                    ifaceClass = fullNames.get(iface);
-                } else {
-                    ifaceClass = ClassUtils.forName(packages, iface).getName();
-                }
-                cls.addInterface(pool.get(ifaceClass));
-            }
+            Arrays.stream(ifaces).forEach(i -> builder.addInterface(i.trim()));
         }
-        String body = source.substring(source.indexOf("{") + 1, 
source.length() - 1);
+        
+        // process constructors, fields, methods
+        String body = source.substring(source.indexOf('{') + 1, 
source.length() - 1);
         String[] methods = METHODS_PATTERN.split(body);
-        for (String method : methods) {
-            method = method.trim();
-            if (method.length() > 0) {
-                if (method.startsWith(className)) {
-                    cls.addConstructor(CtNewConstructor.make("public " + 
method, cls));
-                } else if (FIELD_PATTERN.matcher(method).matches()) {
-                    cls.addField(CtField.make("private " + method, cls));
-                } else {
-                    cls.addMethod(CtNewMethod.make("public " + method, cls));
-                }
+        String className = ClassUtils.getSimpleClassName(name);
+        Arrays.stream(methods).map(String::trim).filter(m -> 
!m.isEmpty()).forEach(method-> {
+            if (method.startsWith(className)) {
+                builder.addConstructor("public " + method);
+            } else if (FIELD_PATTERN.matcher(method).matches()) {
+                builder.addField("private " + method);
+            } else {
+                builder.addMethod("public " + method);
             }
-        }
-        return cls.toClass(ClassHelper.getCallerClassLoader(getClass()), 
JavassistCompiler.class.getProtectionDomain());
+        });
+        
+        // compile
+        ClassLoader classLoader = ClassHelper.getCallerClassLoader(getClass());
+        CtClass cls = builder.build(classLoader);
+        return cls.toClass(classLoader, 
JavassistCompiler.class.getProtectionDomain());
     }
 
 }
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/ClassUtilsTest.java
 
b/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/ClassUtilsTest.java
index 2ebf668..8acf00b 100644
--- 
a/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/ClassUtilsTest.java
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/ClassUtilsTest.java
@@ -146,6 +146,13 @@ public class ClassUtilsTest {
     public void testGetSizeMethod() {
         Assertions.assertEquals("getLength()", 
ClassUtils.getSizeMethod(GenericClass3.class));
     }
+    
+    @Test
+    public void testGetSimpleClassName() {
+        Assertions.assertNull(ClassUtils.getSimpleClassName(null));
+        Assertions.assertEquals("Map", 
ClassUtils.getSimpleClassName(Map.class.getName()));
+        Assertions.assertEquals("Map", 
ClassUtils.getSimpleClassName(Map.class.getSimpleName()));
+    }
 
     private interface GenericInterface<T> {
     }

Reply via email to