/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.factory;
import java.util.Iterator;
import org.geotoolkit.util.collection.DeferringIterator;
/**
* An iterator which move at the end of the iteration any class not loaded by the context
* class loader or one of its parents/children.
*
* @author Martin Desruisseaux (Geomatys)
* @version 3.20
*
* @see Factories#orderForClassLoader(Iterator, ClassLoader)
*
* @since 3.20
* @module
*/
final class OrderedIterator<T> extends DeferringIterator<T> {
/**
* The desired class loader (never {@code null}).
*/
final ClassLoader classLoader;
/**
* Creates a new ordered iterator.
*
* @param classLoader The desired class loader.
* @param iterator The iterator to wrap.
*/
OrderedIterator(final ClassLoader classLoader, final Iterator<T> iterator) {
super(iterator);
this.classLoader = classLoader;
}
/**
* Returns {@code true} if the given element does not use the expected class loader.
*/
@Override
protected boolean isDeferred(final T element) {
if (element == null) {
return false;
}
final ClassLoader nc = element.getClass().getClassLoader(); // May be null.
for (ClassLoader c=classLoader; c != null;) {
c = c.getParent(); // May be null, which we want to test.
if (c == nc) {
// Loaded by the desired class loader or one of its parents.
// This is the case of standard services (PNG or JPEG images).
return false;
}
}
for (ClassLoader c=nc; c!=null; c=c.getParent()) {
if (c == classLoader) {
// Loaded by the desired class loader or one of its children.
// This is the case of services defined by the library.
return false;
}
}
// In the tree of ClassLoaders, the 'nc' classloader is not on the
// same "branch" than the desired classloader.
return true;
}
}