    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 * http://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019
    020package org.apache.commons.compress.utils;
    021
    022import java.util.Iterator;
    023import java.util.NoSuchElementException;
    024import java.util.ServiceConfigurationError;
    025import java.util.ServiceLoader;
    026
    027/**
    028 * Iterates all services for a given class through the standard
    029 * {@link ServiceLoader} mechanism.
    030 *
    031 * @param <E>
    032 *            The service to load
    033 * @since 1.13
    034 */
    035public class ServiceLoaderIterator<E> implements Iterator<E> {
    036
    037    private E nextServiceLoader;
    038    private final Class<E> service;
    039    private final Iterator<E> serviceLoaderIterator;
    040
    041    public ServiceLoaderIterator(final Class<E> service) {
    042        this(service, ClassLoader.getSystemClassLoader());
    043    }
    044
    045    public ServiceLoaderIterator(final Class<E> service, final ClassLoader classLoader) {
    046        this.service = service;
    047        final ServiceLoader<E> serviceLoader = ServiceLoader.load(service, classLoader);
    048        serviceLoaderIterator = serviceLoader.iterator();
    049        nextServiceLoader = null;
    050    }
    051
    052    private boolean getNextServiceLoader() {
    053        while (nextServiceLoader == null) {
    054            try {
    055                if (!serviceLoaderIterator.hasNext()) {
    056                    return false;
    057                }
    058                nextServiceLoader = serviceLoaderIterator.next();
    059            } catch (final ServiceConfigurationError e) {
    060                if (e.getCause() instanceof SecurityException) {
    061                    // Ignore security exceptions
    062                    // TODO Log?
    063                    continue;
    064                }
    065                throw e;
    066            }
    067        }
    068        return true;
    069    }
    070
    071    @Override
    072    public boolean hasNext() {
    073        return getNextServiceLoader();
    074    }
    075
    076    @Override
    077    public E next() {
    078        if (!getNextServiceLoader()) {
    079            throw new NoSuchElementException("No more elements for service " + service.getName());
    080        }
    081        final E tempNext = nextServiceLoader;
    082        nextServiceLoader = null;
    083        return tempNext;
    084    }
    085
    086    @Override
    087    public void remove() {
    088        throw new UnsupportedOperationException("service=" + service.getName());
    089    }
    090
    091}