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 }