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

com.loyayz.gaia.exception.ExceptionDisposers Maven / Gradle / Ivy

package com.loyayz.gaia.exception;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.core.ExceptionDepthComparator;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;

import java.util.*;

/**
 * @author loyayz ([email protected])
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ExceptionDisposers {
    private static Map, ExceptionDisposer> mapped = new HashMap<>(16);
    private static Map, ExceptionDisposer> lookupCache = new HashMap<>(16);
    private static ExceptionDisposer defaultExceptionDisposer = new AbstractExceptionDisposer() {
        @Override
        protected void doAddExceptions() {

        }
    };

    public synchronized static void addExceptionDisposer(ExceptionDisposer disposer) {
        addExceptionDisposers(Collections.singletonList(disposer));
    }

    public synchronized static void addExceptionDisposers(List disposers) {
        if (disposers == null) {
            return;
        }
        for (ExceptionDisposer disposer : disposers) {
            addMappedDisposer(disposer);
        }
        lookupCache.clear();
    }

    /**
     * Find a {@link ExceptionDisposer} to handle the given Throwable.
     * Use {@link ExceptionDepthComparator} if more than one match is found.
     *
     * @param exception the exception
     * @return a {@link ExceptionDisposer} to handle the exception, or {@link #defaultExceptionDisposer} if none found
     */
    public static ExceptionDisposer resolveByException(Throwable exception) {
        ExceptionDisposer result = null;
        ExceptionDisposer topDisposer = resolveByExceptionType(Throwable.class);
        if (topDisposer == null) {
            topDisposer = defaultExceptionDisposer;
        }
        while (exception != null) {
            result = resolveByExceptionType(exception.getClass());
            if (result != null && result != topDisposer) {
                break;
            }
            exception = exception.getCause();
        }
        return result == null ? topDisposer : result;
    }

    /**
     * Find a {@link ExceptionDisposer} to handle the given Throwable.
     * Use {@link ExceptionDepthComparator} if more than one match is found.
     *
     * @param exceptionType the exception type
     * @return a ExceptionDisposer to handle the exception, or {@code null} if none found
     */
    public static ExceptionDisposer resolveByExceptionType(Class exceptionType) {
        ExceptionDisposer result = lookupCache.get(exceptionType);
        if (result == null) {
            result = getMappedDisposer(exceptionType);
            lookupCache.put(exceptionType, result);
        }
        return result;
    }

    private static ExceptionDisposer getMappedDisposer(Class exceptionType) {
        ExceptionDisposer result = mapped.get(exceptionType);
        if (result != null) {
            return result;
        }
        List> matches = new ArrayList<>();
        for (Class mappedException : mapped.keySet()) {
            if (mappedException.isAssignableFrom(exceptionType)) {
                matches.add(mappedException);
            }
        }
        if (matches.isEmpty()) {
            return null;
        }
        matches.sort(new ExceptionDepthComparator(exceptionType));
        return mapped.get(matches.get(0));
    }

    private static void addMappedDisposer(ExceptionDisposer disposer) {
        for (Class exception : disposer.exceptions()) {
            ExceptionDisposer store = disposer;
            // 同类型,根据 @Order 排序
            if (mapped.containsKey(exception)) {
                ExceptionDisposer old = mapped.get(exception);
                store = AnnotationAwareOrderComparator.INSTANCE
                        .compare(old, disposer) < 0 ? old : disposer;
            }
            mapped.put(exception, store);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy