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);
+ }
+}