/** * Implementation of {@link #getServiceProviders(Class, Filter, Hints)} without the filtering * applied by the {@link #isAcceptable(Object, Class, Hints, Filter)} method. If this filtering is * not already presents in the filter given to this method, then it must be applied on the * elements returned by the iterator. The later is preferrable when: * * <p> * * <ul> * <li>There is some cheaper tests to perform before {@code isAcceptable}. * <li>We don't want a restrictive filter in order to avoid trigging a classpath scan if this * method doesn't found any element to iterate. * </ul> * * <p><b>Note:</b> {@link #synchronizeIteratorProviders} should also be invoked once before this * method. * * @todo Use Hints to match Constructor. */ final <T> Iterator<T> getUnfilteredProviders(final Class<T> category) { /* * If the map is not empty, then this mean that a scanning is under progress, i.e. * 'scanForPlugins' is currently being executed. This is okay as long as the user * is not asking for one of the categories under scanning. Otherwise, the answer * returned by 'getServiceProviders' would be incomplete because not all plugins * have been found yet. This can lead to some bugs hard to spot because this methoud * could complete normally but return the wrong plugin. It is safer to thrown an * exception so the user is advised that something is wrong. */ if (scanningCategories.contains(category)) { throw new RecursiveSearchException(category); } scanForPluginsIfNeeded(category); return getServiceProviders(category, true); }
/** * Returns the providers in the registry for the specified category, filter and hints. Providers * that are not {@linkplain OptionalFactory#isAvailable available} will be ignored. This method * will {@linkplain #scanForPlugins() scan for plugins} the first time it is invoked for the given * category. * * @param <T> The class represented by the {@code category} argument. * @param category The category to look for. Usually an interface class (not the actual * implementation class). * @param filter The optional filter, or {@code null}. * @param hints The optional user requirements, or {@code null}. * @return Factories ready to use for the specified category, filter and hints. * @since 2.3 */ public synchronized <T> Iterator<T> getServiceProviders( final Class<T> category, final Filter filter, final Hints hints) { /* * The implementation of this method is very similar to the 'getUnfilteredProviders' * one except for filter handling. See the comments in 'getUnfilteredProviders' for * more implementation details. */ if (scanningCategories.contains(category)) { // Please note you will get errors here if you accidentally allow // more than one thread to use your FactoryRegistry at a time. throw new RecursiveSearchException(category); } final Filter hintsFilter = new Filter() { public boolean filter(final Object provider) { return isAcceptable(category.cast(provider), category, hints, filter); } }; synchronizeIteratorProviders(); scanForPluginsIfNeeded(category); return getServiceProviders(category, hintsFilter, true); }