    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        this.serviceLoaderIterator = ServiceLoader.load(service, classLoader).iterator();
    048    }
    049
    050    @Override
    051    public boolean hasNext() {
    052        while (nextServiceLoader == null) {
    053            try {
    054                if (!serviceLoaderIterator.hasNext()) {
    055                    return false;
    056                }
    057                nextServiceLoader = serviceLoaderIterator.next();
    058            } catch (final ServiceConfigurationError e) {
    059                if (e.getCause() instanceof SecurityException) {
    060                    // Ignore security exceptions
    061                    // TODO Log?
    062                    continue;
    063                }
    064                throw e;
    065            }
    066        }
    067        return true;
    068    }
    069
    070    @Override
    071    public E next() {
    072        if (!hasNext()) {
    073            throw new NoSuchElementException("No more elements for service " + service.getName());
    074        }
    075        final E tempNext = nextServiceLoader;
    076        nextServiceLoader = null;
    077        return tempNext;
    078    }
    079
    080    @Override
    081    public void remove() {
    082        throw new UnsupportedOperationException("service=" + service.getName());
    083    }
    084
    085}