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}