001package com.nimbusds.common.spi;
002
003
004import java.util.*;
005
006
007/**
008 * Service (SPI) loader utility.
009 */
010public class ServiceLoaderUtility {
011        
012        
013        /**
014         * Loads a single Service Provider Interface (SPI) implementation.
015         *
016         * @param tClass      The SPI. Not {@code null}.
017         * @param defaultImpl The default implementation, {@code null} if not
018         *                    specified.
019         *
020         * @return The loaded SPI implementation or the default one.
021         *
022         * @throws RuntimeException If more than one SPI implementation was
023         *                          found.
024         */
025        public static <T> T loadSingle(final Class<T> tClass, final T defaultImpl) {
026                
027                List<T> impls = new LinkedList<>();
028                
029                for (T t : ServiceLoader.load(tClass)) {
030                        impls.add(t);
031                }
032                
033                if (impls.isEmpty()) {
034                        return defaultImpl;
035                }
036                
037                if (impls.size() > 1) {
038                        
039                        List<String> classNames = new LinkedList<>();
040                        
041                        for (T impl: impls) {
042                                classNames.add(impl.getClass().getName());
043                        }
044                        
045                        throw new RuntimeException("More than one " + tClass.getName() + " SPI implementation found: " + classNames);
046                }
047                
048                return impls.get(0);
049        }
050        
051        
052        /**
053         * Loads multiple Service Provider Interface (SPI) implementations.
054         *
055         * @param tClass      The SPI. Not {@code null}.
056         * @param defaultImpl The default implementation, {@code null} if not
057         *                    specified.
058         *
059         * @return The loaded SPI implementations, if none were loaded and a
060         *         default was specified, a singleton set with it.
061         */
062        public static <T> Set<T> loadMultiple(final Class<T> tClass, final T defaultImpl) {
063                
064                Set<T> impls = new HashSet<>();
065                
066                for (T t : ServiceLoader.load(tClass)) {
067                        impls.add(t);
068                }
069                
070                if (impls.isEmpty() && defaultImpl != null) {
071                        impls.add(defaultImpl);
072                }
073                
074                return impls;
075        }
076}