001/*
002 *    Copyright 2024-2025, Warm-Flow (290631660@qq.com).
003 *
004 *    Licensed under the Apache License, Version 2.0 (the "License");
005 *    you may not use this file except in compliance with the License.
006 *    You may obtain a copy of the License at
007 *
008 *       https://www.apache.org/licenses/LICENSE-2.0
009 *
010 *    Unless required by applicable law or agreed to in writing, software
011 *    distributed under the License is distributed on an "AS IS" BASIS,
012 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *    See the License for the specific language governing permissions and
014 *    limitations under the License.
015 */
016package org.dromara.warm.flow.core.utils;
017
018import java.security.AccessController;
019import java.security.PrivilegedAction;
020import java.util.*;
021
022/**
023 * SPI机制中的服务加载工具类
024 *
025 * @author warm
026 */
027public class ServiceLoaderUtil {
028
029    /**
030     * 。加载第一个可用服务,如果用户定义了多个接口实现类,只获取第一个不报错的服务
031     *
032     * @param <T>   接口类型
033     * @param clazz 服务接口
034     * @return 第一个服务接口实现对象,无实现返回{@code null}
035     */
036    public static <T> T loadFirst(Class<T> clazz) {
037        final Iterator<T> iterator = load(clazz).iterator();
038        while (iterator.hasNext()) {
039            try {
040                return iterator.next();
041            } catch (ServiceConfigurationError ignore) {
042
043            }
044        }
045        return null;
046    }
047
048    /**
049     * 加载服务 并已list列表返回
050     *
051     * @param <T>   接口类型
052     * @param clazz 服务接口
053     * @return 服务接口实现列表
054     * @since 5.4.2
055     */
056    public static <T> List<T> loadList(Class<T> clazz) {
057        List<T> list = new ArrayList<>();
058        ServiceLoader<T> serviceLoader = load(clazz);
059        Iterator<T> serviceIterator = serviceLoader.iterator();
060        while (serviceIterator.hasNext()) {
061            try {
062                list.add(serviceIterator.next());
063            } catch (ServiceConfigurationError ignore) {
064
065            }
066        }
067        return list;
068    }
069
070    /**
071     * 加载服务
072     *
073     * @param <T>   接口类型
074     * @param clazz 服务接口
075     * @return 服务接口实现列表
076     */
077    public static <T> ServiceLoader<T> load(Class<T> clazz) {
078        return load(clazz, null);
079    }
080
081    /**
082     * 加载服务
083     *
084     * @param <T>    接口类型
085     * @param clazz  服务接口
086     * @param loader {@link ClassLoader}
087     * @return 服务接口实现列表
088     */
089    public static <T> ServiceLoader<T> load(Class<T> clazz, ClassLoader loader) {
090        return ServiceLoader.load(clazz, ObjectUtil.defaultIfNull(loader, ServiceLoaderUtil::getClassLoader));
091    }
092
093    /**
094     * 获取{@link ClassLoader}<br>
095     * 获取顺序如下:<br>
096     *
097     * <pre>
098     * 1、获取当前线程的ContextClassLoader
099     * 2、获取当前类对应的ClassLoader
100     * 3、获取系统ClassLoader({@link ClassLoader#getSystemClassLoader()})
101     * </pre>
102     *
103     * @return 类加载器
104     */
105    public static ClassLoader getClassLoader() {
106        ClassLoader classLoader = getContextClassLoader();
107        if (classLoader == null) {
108            classLoader = ServiceLoaderUtil.class.getClassLoader();
109            if (null == classLoader) {
110                classLoader = getSystemClassLoader();
111            }
112        }
113        return classLoader;
114    }
115
116    /**
117     * 获取当前线程的{@link ClassLoader}
118     *
119     * @return 当前线程的class loader
120     * @see Thread#getContextClassLoader()
121     */
122    public static ClassLoader getContextClassLoader() {
123        if (System.getSecurityManager() == null) {
124            return Thread.currentThread().getContextClassLoader();
125        } else {
126            // 绕开权限检查
127            return AccessController.doPrivileged(
128                    (PrivilegedAction<ClassLoader>) () -> Thread.currentThread().getContextClassLoader());
129        }
130    }
131
132    /**
133     * 获取系统{@link ClassLoader}
134     *
135     * @return 系统{@link ClassLoader}
136     * @see ClassLoader#getSystemClassLoader()
137     * @since 5.7.0
138     */
139    public static ClassLoader getSystemClassLoader() {
140        if (System.getSecurityManager() == null) {
141            return ClassLoader.getSystemClassLoader();
142        } else {
143            // 绕开权限检查
144            return AccessController.doPrivileged(
145                    (PrivilegedAction<ClassLoader>) ClassLoader::getSystemClassLoader);
146        }
147    }
148
149}