001 /*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 * http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014 package org.apache.commons.classscan.util;
015
016 import java.util.Iterator;
017 import java.util.ServiceConfigurationError;
018 import java.util.ServiceLoader;
019
020 import org.slf4j.Logger;
021 import org.slf4j.LoggerFactory;
022
023 /**
024 * Visit the provider instances specified in the META-INF/services directories
025 *
026 * @param <T> The type of the provider
027 */
028 public abstract class ServiceVisitor<T> {
029
030 private static final Logger logger = LoggerFactory.getLogger(ServiceVisitor.class);
031
032 /**
033 * Visit the service provider available for the given interface and ClassLoader
034 *
035 * @param serviceInterface The interface of the service
036 * @param classLoader The ClassLoader which will load the service
037 */
038 public void visitProviders(Class<T> serviceInterface, ClassLoader classLoader) {
039 Iterator<T> factories = ServiceLoader.load(serviceInterface, classLoader).iterator();
040 for(;;) {
041 // this odd loop is due to the possibility of the iterator throwing
042 // ServiceConfigurationError from either hasNext() or next()
043 try {
044 if(!factories.hasNext()) {
045 break;
046 }
047 T factory = factories.next();
048 if(!visit(factory)) {
049 break;
050 }
051 }
052 catch(ServiceConfigurationError error) {
053 logger.warn("Ignoring configuration error", error);
054 }
055 }
056 }
057
058 /**
059 * The callback method which is invoked upon finding a service provider
060 *
061 * @param serviceProvider An instance of the service provider
062 * @return true, if additional service providers desired; false, stop the visiting
063 */
064 abstract protected boolean visit(T serviceProvider);
065 }