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

fanjia pushed a commit to branch st-engine
in repository https://gitbox.apache.org/repos/asf/incubator-seatunnel.git


The following commit(s) were added to refs/heads/st-engine by this push:
     new 19523fe8e [Feature][st-engine] Add user-defined class loader (#2383)
19523fe8e is described below

commit 19523fe8e919443a5c1582978976fdc7da234d5c
Author: TyrantLucifer <[email protected]>
AuthorDate: Fri Aug 12 10:22:45 2022 +0800

    [Feature][st-engine] Add user-defined class loader (#2383)
    
    * [Feature][st-engine] Add user-defined class loader (#2345)
    
    * [Feature][st-engine] Add child-first and parent-first class loader
---
 .../common/loader/SeatunnelBaseClassLoader.java    |  56 ++++++++++
 .../loader/SeatunnelChildFirstClassLoader.java     | 121 +++++++++++++++++++++
 .../loader/SeatunnelParentFirstClassLoader.java    |  28 +++++
 3 files changed, 205 insertions(+)

diff --git 
a/seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/loader/SeatunnelBaseClassLoader.java
 
b/seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/loader/SeatunnelBaseClassLoader.java
new file mode 100644
index 000000000..2655be861
--- /dev/null
+++ 
b/seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/loader/SeatunnelBaseClassLoader.java
@@ -0,0 +1,56 @@
+/*
+ * 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.seatunnel.engine.common.loader;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.List;
+import java.util.function.Consumer;
+
+public abstract class SeatunnelBaseClassLoader extends URLClassLoader {
+    protected static final Consumer<Throwable> NOOP_EXCEPTION_HANDLER = 
classLoadingException -> {};
+
+    private final Consumer<Throwable> classLoadingExceptionHandler;
+
+    protected SeatunnelBaseClassLoader(List<URL> urls) {
+        this(urls.toArray(new URL[0]), 
SeatunnelBaseClassLoader.class.getClassLoader());
+    }
+
+    protected SeatunnelBaseClassLoader(URL[] urls, ClassLoader parent) {
+        this(urls, parent, NOOP_EXCEPTION_HANDLER);
+    }
+
+    protected SeatunnelBaseClassLoader(URL[] urls, ClassLoader parent, 
Consumer<Throwable> classLoadingExceptionHandler) {
+        super(urls, parent);
+        this.classLoadingExceptionHandler = classLoadingExceptionHandler;
+    }
+
+    @Override
+    protected final Class<?> loadClass(String name, boolean resolve) throws 
ClassNotFoundException {
+        try {
+            return loadClassWithoutExceptionHandling(name, resolve);
+        } catch (Throwable classLoadingException) {
+            classLoadingExceptionHandler.accept(classLoadingException);
+            throw classLoadingException;
+        }
+    }
+
+    protected Class<?> loadClassWithoutExceptionHandling(String name, boolean 
resolve) throws ClassNotFoundException {
+        return super.loadClass(name, resolve);
+    }
+}
diff --git 
a/seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/loader/SeatunnelChildFirstClassLoader.java
 
b/seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/loader/SeatunnelChildFirstClassLoader.java
new file mode 100644
index 000000000..26ac5f1ad
--- /dev/null
+++ 
b/seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/loader/SeatunnelChildFirstClassLoader.java
@@ -0,0 +1,121 @@
+/*
+ * 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.seatunnel.engine.common.loader;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Consumer;
+
+public class SeatunnelChildFirstClassLoader extends SeatunnelBaseClassLoader {
+    private final String[] alwaysParentFirstPatterns;
+    private static final String SEATUNNEL_CLASS_PATTERN = 
"org.apache.seatunnel.";
+
+    public SeatunnelChildFirstClassLoader(List<URL> urls) {
+        this(urls, new String[]{SEATUNNEL_CLASS_PATTERN});
+    }
+
+    public SeatunnelChildFirstClassLoader(List<URL> urls, String[] 
alwaysParentFirstPatterns) {
+        this(urls.toArray(new URL[0]),
+                SeatunnelChildFirstClassLoader.class.getClassLoader(),
+                alwaysParentFirstPatterns,
+                NOOP_EXCEPTION_HANDLER);
+    }
+
+    public SeatunnelChildFirstClassLoader(
+            URL[] urls,
+            ClassLoader parent,
+            String[] alwaysParentFirstPatterns,
+            Consumer<Throwable> classLoadingExceptionHandler) {
+        super(urls, parent, classLoadingExceptionHandler);
+        this.alwaysParentFirstPatterns = alwaysParentFirstPatterns;
+    }
+
+    @Override
+    protected synchronized Class<?> loadClassWithoutExceptionHandling(
+            String name,
+            boolean resolve) throws ClassNotFoundException {
+        // First, check if the class has already been loaded
+        Class<?> c = findLoadedClass(name);
+
+        if (c == null) {
+            // check whether the class should go parent-first
+            for (String alwaysParentFirstPattern : alwaysParentFirstPatterns) {
+                if (name.startsWith(alwaysParentFirstPattern)) {
+                    return super.loadClassWithoutExceptionHandling(name, 
resolve);
+                }
+            }
+
+            try {
+                // check the URLs
+                c = findClass(name);
+            } catch (ClassNotFoundException e) {
+                // let URLClassLoader do it, which will eventually call the 
parent
+                c = super.loadClassWithoutExceptionHandling(name, resolve);
+            }
+        }
+
+        if (resolve) {
+            resolveClass(c);
+        }
+        return c;
+    }
+
+    @Override
+    public URL getResource(String name) {
+        // first, try and find it via the URLClassloader
+        URL urlClassLoaderResource = findResource(name);
+        if (urlClassLoaderResource != null) {
+            return urlClassLoaderResource;
+        }
+        // delegate to super
+        return super.getResource(name);
+    }
+
+    @Override
+    public Enumeration<URL> getResources(String name) throws IOException {
+        // first get resources from URLClassloader
+        Enumeration<URL> urlClassLoaderResources = findResources(name);
+        final List<URL> result = new ArrayList<>();
+
+        while (urlClassLoaderResources.hasMoreElements()) {
+            result.add(urlClassLoaderResources.nextElement());
+        }
+
+        // get parent urls
+        Enumeration<URL> parentResources = getParent().getResources(name);
+        while (parentResources.hasMoreElements()) {
+            result.add(parentResources.nextElement());
+        }
+
+        return new Enumeration<URL>() {
+            Iterator<URL> iter = result.iterator();
+
+            public boolean hasMoreElements() {
+                return iter.hasNext();
+            }
+
+            public URL nextElement() {
+                return iter.next();
+            }
+        };
+    }
+}
diff --git 
a/seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/loader/SeatunnelParentFirstClassLoader.java
 
b/seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/loader/SeatunnelParentFirstClassLoader.java
new file mode 100644
index 000000000..e843c0633
--- /dev/null
+++ 
b/seatunnel-engine/seatunnel-engine-common/src/main/java/org/apache/seatunnel/engine/common/loader/SeatunnelParentFirstClassLoader.java
@@ -0,0 +1,28 @@
+/*
+ * 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.seatunnel.engine.common.loader;
+
+import java.net.URL;
+import java.util.List;
+
+public class SeatunnelParentFirstClassLoader extends SeatunnelBaseClassLoader {
+
+    public SeatunnelParentFirstClassLoader(List<URL> urls) {
+        super(urls);
+    }
+}

Reply via email to