Make shared class filter for InstanceClassLoader pluggable

Patch by David Capwell; reviewed by Jon Meredith and Alex Petrov for CASSANDRA-15713.
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index bb3d907..86a9490 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,3 +1,4 @@
 # 0.0.2
 
-CASSANDRA-15684: improve error codes in NodeToolResult to produce better errors and to allow Any style message checks
+CASSANDRA-15684: Improve error codes in NodeToolResult to produce better errors and to allow Any style message checks
+CASSANDRA-15713: Make shared class filter for InstanceClassLoader pluggable
diff --git a/src/main/java/org/apache/cassandra/distributed/shared/InstanceClassLoader.java b/src/main/java/org/apache/cassandra/distributed/shared/InstanceClassLoader.java
index 4f2fc8a..51cd14a 100644
--- a/src/main/java/org/apache/cassandra/distributed/shared/InstanceClassLoader.java
+++ b/src/main/java/org/apache/cassandra/distributed/shared/InstanceClassLoader.java
@@ -26,33 +26,46 @@
 
 public class InstanceClassLoader extends URLClassLoader
 {
-    private static final Predicate<String> sharePackage = name ->
-                                                          name.startsWith("org.apache.cassandra.distributed.api.")
-                                                          || name.startsWith("org.apache.cassandra.distributed.shared.")
-                                                          || name.startsWith("sun.")
-                                                          || name.startsWith("oracle.")
-                                                          || name.startsWith("com.intellij.")
-                                                          || name.startsWith("com.sun.")
-                                                          || name.startsWith("com.oracle.")
-                                                          || name.startsWith("java.")
-                                                          || name.startsWith("javax.")
-                                                          || name.startsWith("jdk.")
-                                                          || name.startsWith("netscape.")
-                                                          || name.startsWith("org.xml.sax.");
+    private static final Predicate<String> DEFAULT_SHARED_PACKAGES =
+              name ->
+              name.startsWith("org.apache.cassandra.distributed.api.")
+              || name.startsWith("org.apache.cassandra.distributed.shared.")
+              || name.startsWith("sun.")
+              || name.startsWith("oracle.")
+              || name.startsWith("com.intellij.")
+              || name.startsWith("com.sun.")
+              || name.startsWith("com.oracle.")
+              || name.startsWith("java.")
+              || name.startsWith("javax.")
+              || name.startsWith("jdk.")
+              || name.startsWith("netscape.")
+              || name.startsWith("org.xml.sax.");
 
     private volatile boolean isClosed = false;
     private final URL[] urls;
     private final int generation; // used to help debug class loader leaks, by helping determine which classloaders should have been collected
     private final int id;
     private final ClassLoader sharedClassLoader;
+    private final Predicate<String> loadShared;
 
     public InstanceClassLoader(int generation, int id, URL[] urls, ClassLoader sharedClassLoader)
     {
+        this(generation, id, urls, sharedClassLoader, DEFAULT_SHARED_PACKAGES);
+    }
+
+    public InstanceClassLoader(int generation, int id, URL[] urls, ClassLoader sharedClassLoader, Predicate<String> loadShared)
+    {
         super(urls, null);
         this.urls = urls;
         this.sharedClassLoader = sharedClassLoader;
         this.generation = generation;
         this.id = id;
+        this.loadShared = loadShared == null ? DEFAULT_SHARED_PACKAGES : loadShared;
+    }
+
+    public static Predicate<String> getDefaultLoadSharedFilter()
+    {
+        return DEFAULT_SHARED_PACKAGES;
     }
 
     public int getClusterGeneration()
@@ -68,7 +81,7 @@
     @Override
     public Class<?> loadClass(String name) throws ClassNotFoundException
     {
-        if (sharePackage.test(name))
+        if (loadShared.test(name))
             return sharedClassLoader.loadClass(name);
 
         return loadClassInternal(name);