All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.flyte.jflyte.utils.ChildFirstClassLoader Maven / Gradle / Ivy

Go to download

Primarily used by jflyte, but can also be used to extend or build a jflyte alternative

There is a newer version: 0.4.60
Show newest version
/*
 * Copyright 2020-2023 Flyte Authors.
 *
 * Licensed 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.flyte.jflyte.utils;

import com.google.errorprone.annotations.Var;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * {@link URLClassLoader} that loads classes into child class loader, instead of parent.
 *
 * 

This way we can keep parent class loader clean from unnecessary classes, and load conflicting * classes into multiple children class loaders. * *

All "api" classes must be loaded in parent class loader, because they act as common interface * between the code in parent class loader, and the code loaded in child class loaders, and we pass * instances of these classes around. */ public class ChildFirstClassLoader extends URLClassLoader { // we have to load these classes in parent class loader // it's base shared between all plugins and user code private static final Set PARENT_FIRST_PACKAGE_PREFIXES = Set.of("org.flyte.api.v1.", "org.flyte.jflyte.api."); private static final Set CHILD_ONLY_PREFIXES = Set.of("org.slf4j.impl.", "org/slf4j/impl/", "META-INF/services/"); @SuppressWarnings("JdkObsolete") private static class CustomEnumeration implements Enumeration { private final Iterator iter; CustomEnumeration(Iterator iter) { this.iter = iter; } @Override public boolean hasMoreElements() { return iter.hasNext(); } @Override public URL nextElement() { return iter.next(); } } public ChildFirstClassLoader(URL[] urls) { super(urls, ChildFirstClassLoader.class.getClassLoader()); } @Override protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { @Var Class cls = findLoadedClass(name); if (cls == null) { if (parentFirst(name)) { return super.loadClass(name, resolve); } try { cls = findClass(name); } catch (ClassNotFoundException e) { if (childOnly(name)) { throw e; } cls = getParent().loadClass(name); } } if (resolve) { resolveClass(cls); } return cls; } @Override public URL getResource(String name) { URL resource = findResource(name); if (resource != null) { return resource; } return childOnly(name) ? null : getParent().getResource(name); } @Override public Enumeration getResources(String name) throws IOException { Enumeration childResources = findResources(name); List allResources = new ArrayList<>(); while (childResources.hasMoreElements()) { allResources.add(childResources.nextElement()); } if (!childOnly(name)) { Enumeration parentResources = getParent().getResources(name); while (parentResources.hasMoreElements()) { allResources.add(parentResources.nextElement()); } } return new CustomEnumeration(allResources.iterator()); } private static boolean parentFirst(String name) { return PARENT_FIRST_PACKAGE_PREFIXES.stream().anyMatch(name::startsWith); } private static boolean childOnly(String name) { return CHILD_ONLY_PREFIXES.stream().anyMatch(name::startsWith); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy