1111import org .jetbrains .annotations .NotNull ;
1212import org .jetbrains .annotations .Nullable ;
1313
14+ import java .security .AccessControlException ;
15+ import java .security .AccessController ;
16+ import java .security .PrivilegedAction ;
1417import java .util .Collections ;
1518import java .util .Comparator ;
1619import java .util .IdentityHashMap ;
20+ import java .util .Iterator ;
1721import java .util .Map ;
22+ import java .util .ServiceConfigurationError ;
1823import java .util .ServiceLoader ;
24+ import java .util .SortedSet ;
25+ import java .util .TreeSet ;
1926import java .util .concurrent .atomic .AtomicReference ;
20- import java .util .stream .StreamSupport ;
2127
2228/**
2329 * Holds a registry of default settings and cache providers.
@@ -104,10 +110,36 @@ public void registerCacheProvider(@NonNull Class<? extends CacheProvider> cacheP
104110 private void populateProviders () {
105111 log .debug ("Xanthic: Registering canonical cache providers from the classpath..." );
106112
107- ServiceLoader <AbstractCacheProvider > load = ServiceLoader .load (AbstractCacheProvider .class );
108- StreamSupport .stream (load .spliterator (), false )
109- .sorted (Comparator .comparingInt (AbstractCacheProvider ::getDiscoveryOrder ))
110- .forEach (provider -> registerCacheProvider (provider .getClass (), provider ));
113+ // prepare service loader
114+ ServiceLoader <AbstractCacheProvider > loader ;
115+ try {
116+ loader = getServiceLoader ();
117+ } catch (ServiceConfigurationError e ) {
118+ log .error ("Failed to create CacheProvider service loader!" , e );
119+ return ;
120+ }
121+
122+ SortedSet <AbstractCacheProvider > loaded = new TreeSet <>(
123+ Comparator .comparingInt (AbstractCacheProvider ::getDiscoveryOrder )
124+ .thenComparing (provider -> provider .getClass ().getName ())
125+ .thenComparingInt (Object ::hashCode )
126+ );
127+
128+ // instantiate providers
129+ Iterator <AbstractCacheProvider > it = loader .iterator ();
130+ while (it .hasNext ()) {
131+ AbstractCacheProvider provider ;
132+ try {
133+ provider = it .next ();
134+ } catch (ServiceConfigurationError | AccessControlException e ) {
135+ log .error ("Failed to instantiate cache provider via service loader!" , e );
136+ continue ;
137+ }
138+ loaded .add (provider );
139+ }
140+
141+ // register providers
142+ loaded .forEach (provider -> registerCacheProvider (provider .getClass (), provider ));
111143
112144 log .debug ("Xanthic: Loaded {} canonical cache provider(s) on settings construction!" , providers .size ());
113145 }
@@ -120,6 +152,18 @@ public static CacheApiSettings getInstance() {
120152 return SingletonHolder .INSTANCE ;
121153 }
122154
155+ private static ServiceLoader <AbstractCacheProvider > getServiceLoader () {
156+ ClassLoader classLoader = CacheApiSettings .class .getClassLoader ();
157+
158+ SecurityManager securityManager = System .getSecurityManager ();
159+ if (securityManager != null ) {
160+ PrivilegedAction <ServiceLoader <AbstractCacheProvider >> action = () -> ServiceLoader .load (AbstractCacheProvider .class , classLoader );
161+ return AccessController .doPrivileged (action );
162+ }
163+
164+ return ServiceLoader .load (AbstractCacheProvider .class , classLoader );
165+ }
166+
123167 private static class SingletonHolder {
124168 private static final CacheApiSettings INSTANCE = new CacheApiSettings ();
125169 }
0 commit comments