103103import com .google .inject .multibindings .ProvidesIntoSet ;
104104
105105public class IMAPServerModule extends AbstractModule {
106+ private static final String SASL_AUTHENTICATION_SERVICE_FACTORY_PROVIDER_EXTENSIONS = "auth.saslAuthenticationServiceFactoryProviderExtensions" ;
107+
106108 private static Stream <Pair <Class , AbstractProcessor >> asPairStream (AbstractProcessor p ) {
107109 return p .acceptableClasses ()
108110 .stream ().map (clazz -> Pair .of (clazz , p ));
@@ -208,25 +210,59 @@ private ImapPackage retrievePackages(GuiceLoader guiceLoader, HierarchicalConfig
208210 }
209211
210212 private SaslMechanismRegistry retrieveSaslMechanisms (SaslMechanismLoader saslMechanismLoader ,
213+ GuiceLoader guiceLoader ,
211214 Set <ImapSaslAuthenticationServiceFactoryProvider > saslAuthenticationServiceFactoryProviders ,
212215 DefaultImapSaslMechanismClassNamesProvider defaultImapSaslMechanismClassNamesProvider ,
213216 HierarchicalConfiguration <ImmutableNode > configuration ) throws ConfigurationException {
214217 ImmutableList <String > mechanismClassNames = retrieveSaslMechanismClassNames (configuration , defaultImapSaslMechanismClassNamesProvider );
215218 ImmutableList <SaslMechanism > mechanisms = saslMechanismLoader .load (mechanismClassNames );
216219 ImmutableList <SaslAuthenticationServiceFactory <?>> saslAuthenticationServiceFactories =
217- retrieveSaslAuthenticationServiceFactories (configuration , saslAuthenticationServiceFactoryProviders );
220+ retrieveSaslAuthenticationServiceFactories (configuration , guiceLoader , saslAuthenticationServiceFactoryProviders );
218221 return new SaslMechanismRegistry (mechanisms , saslAuthenticationServiceFactories );
219222 }
220223
221224 ImmutableList <SaslAuthenticationServiceFactory <?>> retrieveSaslAuthenticationServiceFactories (HierarchicalConfiguration <ImmutableNode > configuration ,
225+ GuiceLoader guiceLoader ,
222226 Set <ImapSaslAuthenticationServiceFactoryProvider > providers ) throws ConfigurationException {
223227 ImmutableList .Builder <SaslAuthenticationServiceFactory <?>> factories = ImmutableList .builder ();
224- for (ImapSaslAuthenticationServiceFactoryProvider provider : providers ) {
228+ ImmutableList <ImapSaslAuthenticationServiceFactoryProvider > allProviders = ImmutableList .<ImapSaslAuthenticationServiceFactoryProvider >builder ()
229+ .addAll (providers )
230+ .addAll (retrieveConfiguredSaslAuthenticationServiceFactoryProviders (configuration , guiceLoader ))
231+ .build ();
232+
233+ for (ImapSaslAuthenticationServiceFactoryProvider provider : allProviders ) {
225234 factories .addAll (provider .provide (configuration ));
226235 }
227236 return factories .build ();
228237 }
229238
239+ ImmutableList <ImapSaslAuthenticationServiceFactoryProvider > retrieveConfiguredSaslAuthenticationServiceFactoryProviders (HierarchicalConfiguration <ImmutableNode > configuration ,
240+ GuiceLoader guiceLoader ) throws ConfigurationException {
241+ if (!configuration .containsKey (SASL_AUTHENTICATION_SERVICE_FACTORY_PROVIDER_EXTENSIONS )) {
242+ return ImmutableList .of ();
243+ }
244+
245+ ImmutableList <String > providerClassNames = Arrays .stream (configuration .getStringArray (SASL_AUTHENTICATION_SERVICE_FACTORY_PROVIDER_EXTENSIONS ))
246+ .flatMap (value -> Arrays .stream (value .split ("," )))
247+ .map (String ::trim )
248+ .collect (ImmutableList .toImmutableList ());
249+
250+ if (providerClassNames .isEmpty () || providerClassNames .stream ().anyMatch (StringUtils ::isBlank )) {
251+ throw new ConfigurationException (SASL_AUTHENTICATION_SERVICE_FACTORY_PROVIDER_EXTENSIONS + " must not be blank when configured" );
252+ }
253+
254+ ImmutableList .Builder <ImapSaslAuthenticationServiceFactoryProvider > providers = ImmutableList .builder ();
255+ for (String providerClassName : providerClassNames ) {
256+ try {
257+ ImapSaslAuthenticationServiceFactoryProvider provider = guiceLoader .instantiate (new ClassName (providerClassName ));
258+ providers .add (provider );
259+ } catch (ClassNotFoundException e ) {
260+ throw new ConfigurationException ("Failed to load " + SASL_AUTHENTICATION_SERVICE_FACTORY_PROVIDER_EXTENSIONS + " class " + providerClassName , e );
261+ }
262+ }
263+ return providers .build ();
264+ }
265+
230266 ImmutableList <String > retrieveSaslMechanismClassNames (HierarchicalConfiguration <ImmutableNode > configuration ,
231267 DefaultImapSaslMechanismClassNamesProvider defaultImapSaslMechanismClassNamesProvider ) throws ConfigurationException {
232268 if (!configuration .containsKey ("auth.saslMechanisms" )) {
@@ -251,7 +287,7 @@ private ThrowingFunction<HierarchicalConfiguration<ImmutableNode>, ImapSuite> im
251287 StatusResponseFactory statusResponseFactory ) {
252288 return configuration -> {
253289 ImapPackage imapPackage = retrievePackages (guiceLoader , configuration );
254- SaslMechanismRegistry saslMechanisms = retrieveSaslMechanisms (saslMechanismLoader , saslAuthenticationServiceFactoryProviders ,
290+ SaslMechanismRegistry saslMechanisms = retrieveSaslMechanisms (saslMechanismLoader , guiceLoader , saslAuthenticationServiceFactoryProviders ,
255291 defaultImapSaslMechanismClassNamesProvider , configuration );
256292 DefaultProcessor processor = provideClassImapProcessors (imapPackage , guiceLoader , saslMechanisms , statusResponseFactory );
257293 ImapEncoder encoder = provideImapEncoder (imapPackage , guiceLoader );
0 commit comments