You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by cr...@apache.org on 2021/10/18 12:10:29 UTC

[dubbo] branch 3.0 updated: Add onlyExtensionClassLoaderPackages support for ExtensionLoader (#9061)

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

crazyhzm pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.0 by this push:
     new f9be618  Add onlyExtensionClassLoaderPackages support for ExtensionLoader (#9061)
f9be618 is described below

commit f9be6184b644e3127df6f13af0076d2618e0b982
Author: Albumen Kevin <jh...@gmail.com>
AuthorDate: Mon Oct 18 20:10:10 2021 +0800

    Add onlyExtensionClassLoaderPackages support for ExtensionLoader (#9061)
    
    * Add onlyExtensionClassLoaderPackages support for ExtensionLoader
    
    * revert temp
---
 .../dubbo/common/extension/ExtensionLoader.java    | 36 ++++++++++++++++------
 .../dubbo/common/extension/LoadingStrategy.java    | 12 ++++++++
 2 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
index 3568cd6..d1dcaae 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
@@ -58,6 +58,7 @@ import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.TreeMap;
@@ -886,10 +887,10 @@ public class ExtensionLoader<T> {
 
     private void loadDirectory(Map<String, Class<?>> extensionClasses, LoadingStrategy strategy, String type) {
         loadDirectory(extensionClasses, strategy.directory(), type, strategy.preferExtensionClassLoader(),
-            strategy.overridden(), strategy.excludedPackages());
+            strategy.overridden(), strategy.excludedPackages(), strategy.onlyExtensionClassLoaderPackages());
         String oldType = type.replace("org.apache", "com.alibaba");
         loadDirectory(extensionClasses, strategy.directory(), oldType, strategy.preferExtensionClassLoader(),
-            strategy.overridden(), strategy.excludedPackages());
+            strategy.overridden(), strategy.excludedPackages(), strategy.onlyExtensionClassLoaderPackages());
     }
 
     /**
@@ -915,11 +916,12 @@ public class ExtensionLoader<T> {
     }
 
     private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type) {
-        loadDirectory(extensionClasses, dir, type, false, false);
+        loadDirectory(extensionClasses, dir, type, false, false, new String[]{}, new String[]{});
     }
 
     private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
-                               boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) {
+                               boolean extensionLoaderClassLoaderFirst, boolean overridden,
+                               String[] excludedPackages, String[] onlyExtensionClassLoaderPackages) {
         String fileName = dir + type;
         try {
             List<ClassLoader> classLoadersToLoad = new LinkedList<>();
@@ -939,7 +941,7 @@ public class ExtensionLoader<T> {
                 Enumeration<java.net.URL> resources = ClassLoader.getSystemResources(fileName);
                 if (resources != null) {
                     while (resources.hasMoreElements()) {
-                        loadResource(extensionClasses, null, resources.nextElement(), overridden, excludedPackages);
+                        loadResource(extensionClasses, null, resources.nextElement(), overridden, excludedPackages, onlyExtensionClassLoaderPackages);
                     }
                 }
             } else {
@@ -948,7 +950,7 @@ public class ExtensionLoader<T> {
 
             Map<ClassLoader, Set<java.net.URL>> resources = ClassLoaderResourceLoader.loadResources(fileName, classLoadersToLoad);
             resources.forEach(((classLoader, urls) -> {
-                loadFromClass(extensionClasses, overridden, urls, classLoader, excludedPackages);
+                loadFromClass(extensionClasses, overridden, urls, classLoader, excludedPackages, onlyExtensionClassLoaderPackages);
             }));
         } catch (Throwable t) {
             logger.error("Exception occurred when loading extension class (interface: " +
@@ -956,16 +958,17 @@ public class ExtensionLoader<T> {
         }
     }
 
-    private void loadFromClass(Map<String, Class<?>> extensionClasses, boolean overridden, Set<java.net.URL> urls, ClassLoader classLoader, String[] excludedPackages) {
+    private void loadFromClass(Map<String, Class<?>> extensionClasses, boolean overridden, Set<java.net.URL> urls, ClassLoader classLoader,
+                               String[] excludedPackages, String[] onlyExtensionClassLoaderPackages) {
         if (CollectionUtils.isNotEmpty(urls)) {
             for (java.net.URL url : urls) {
-                loadResource(extensionClasses, classLoader, url, overridden, excludedPackages);
+                loadResource(extensionClasses, classLoader, url, overridden, excludedPackages, onlyExtensionClassLoaderPackages);
             }
         }
     }
 
     private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
-                              java.net.URL resourceURL, boolean overridden, String... excludedPackages) {
+                              java.net.URL resourceURL, boolean overridden, String[] excludedPackages, String[] onlyExtensionClassLoaderPackages) {
         try {
             try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
                 String line;
@@ -986,7 +989,8 @@ public class ExtensionLoader<T> {
                             } else {
                                 clazz = line;
                             }
-                            if (StringUtils.isNotEmpty(clazz) && !isExcluded(clazz, excludedPackages)) {
+                            if (StringUtils.isNotEmpty(clazz) && !isExcluded(clazz, excludedPackages)
+                                && !isExcludedByClassLoader(clazz, classLoader, onlyExtensionClassLoaderPackages)) {
                                 loadClass(extensionClasses, resourceURL, Class.forName(clazz, true, classLoader), name, overridden);
                             }
                         } catch (Throwable t) {
@@ -1014,6 +1018,18 @@ public class ExtensionLoader<T> {
         return false;
     }
 
+    private boolean isExcludedByClassLoader(String className, ClassLoader classLoader, String... onlyExtensionClassLoaderPackages) {
+        if (onlyExtensionClassLoaderPackages != null) {
+            for (String excludePackage : onlyExtensionClassLoaderPackages) {
+                if (className.startsWith(excludePackage + ".")) {
+                    // if target classLoader is not ExtensionLoader's classLoader should be excluded
+                    return !Objects.equals(ExtensionLoader.class.getClassLoader(), classLoader);
+                }
+            }
+        }
+        return false;
+    }
+
     private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name,
                            boolean overridden) throws NoSuchMethodException {
         if (!type.isAssignableFrom(clazz)) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/LoadingStrategy.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/LoadingStrategy.java
index 2d4faf5..70c49c1 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/LoadingStrategy.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/LoadingStrategy.java
@@ -31,6 +31,18 @@ public interface LoadingStrategy extends Prioritized {
     }
 
     /**
+     * To restrict some class that should loaded from Dubbo's ClassLoader.
+     * For example, we can restrict the class declaration in `org.apache.dubbo` package should
+     * be loaded from Dubbo's ClassLoader and users cannot declare these classes.
+     *
+     * @return class packages should loaded
+     * @since 3.0.4
+     */
+    default String[] onlyExtensionClassLoaderPackages() {
+        return new String[]{};
+    }
+
+    /**
      * Indicates current {@link LoadingStrategy} supports overriding other lower prioritized instances or not.
      *
      * @return if supports, return <code>true</code>, or <code>false</code>