/** * Scans for factory plug-ins of the given category, with guard against recursivities. The * recursivity check make debugging easier than inspecting a {@link StackOverflowError}. * * @param loader The class loader to use. * @param category The category to scan for plug-ins. */ private <T> void scanForPlugins(final Collection<ClassLoader> loaders, final Class<T> category) { if (!scanningCategories.addAndCheck(category)) { throw new RecursiveSearchException(category); } try { final StringBuilder message = getLogHeader(category); boolean newServices = false; /* * First, scan META-INF/services directories (the default mechanism). */ for (final ClassLoader loader : loaders) { newServices |= register(lookupProviders(category, loader), category, message); newServices |= registerFromSystemProperty(loader, category, message); } /* * Next, query the user-provider iterators, if any. */ final FactoryIteratorProvider[] fip = FactoryIteratorProviders.getIteratorProviders(); for (int i = 0; i < fip.length; i++) { final Iterator<T> it = fip[i].iterator(category); if (it != null) { newServices |= register(it, category, message); } } /* * Finally, log the list of registered factories. */ if (newServices) { log("scanForPlugins", message); } } finally { scanningCategories.removeAndCheck(category); } }
/** * Synchronizes the content of the {@link #globalConfiguration} with {@link * FactoryIteratorProviders#GLOBAL}. New providers are {@linkplain #register registered} * immediately. Note that this method is typically invoked in a different thread than {@link * FactoryIteratorProviders} method calls. * * @see FactoryIteratorProviders#addFactoryIteratorProvider */ private void synchronizeIteratorProviders() { final FactoryIteratorProvider[] newProviders = globalConfiguration.synchronizeIteratorProviders(); if (newProviders == null) { return; } for (final Iterator<Class<?>> categories = getCategories(); categories.hasNext(); ) { final Class<?> category = categories.next(); if (needScanForPlugins == null || !needScanForPlugins.contains(category)) { /* * Register immediately the factories only if some other factories were already * registered for this category, because in such case scanForPlugin() will not * be invoked automatically. If no factory are registered for this category, do * nothing - we will rely on the lazy invocation of scanForPlugins() when first * needed. We perform this check because getServiceProviders(category).hasNext() * is the criterion used by FactoryRegistry in order to decide if it should invoke * automatically scanForPlugins(). */ for (int i = 0; i < newProviders.length; i++) { register(newProviders[i], category); } } } }