class ClassLoaderOrder {
    /** The {@link ClassLoader} order. */
    private final List<Entry<ClassLoader, ClassLoaderHandlerRegistryEntry>> classLoaderOrder = new ArrayList<>();

    public ReflectionUtils reflectionUtils;

    /**
     * The set of all {@link ClassLoader} instances that have been added to the order so far, so that classloaders
     * don't get added twice.
     */
    // Need to use IdentityHashMap for maps and sets here, because TomEE weirdly makes instances of
    // CxfContainerClassLoader equal to (via .equals()) the instance of TomEEWebappClassLoader that it
    // delegates to (#515)
    private final Set<ClassLoader> added = Collections.newSetFromMap(new IdentityHashMap<ClassLoader, Boolean>());

    /**
     * The set of all {@link ClassLoader} instances that have been delegated to so far, to prevent an infinite loop
     * in delegation.
     */
    private final Set<ClassLoader> delegatedTo = Collections
            .newSetFromMap(new IdentityHashMap<ClassLoader, Boolean>());

    /**
     * The set of all parent {@link ClassLoader} instances that have been delegated to so far, to enable
     * {@link ClassGraph#ignoreParentClassLoaders()}.
     */
    private final Set<ClassLoader> allParentClassLoaders = Collections
            .newSetFromMap(new IdentityHashMap<ClassLoader, Boolean>());

    /** A map from {@link ClassLoader} to {@link ClassLoaderHandlerRegistryEntry}. */
    private final Map<ClassLoader, ClassLoaderHandlerRegistryEntry> classLoaderToClassLoaderHandlerRegistryEntry = //
            new IdentityHashMap<>();

    // -------------------------------------------------------------------------------------------------------------

    public ClassLoaderOrder(final ReflectionUtils reflectionUtils) {
        this.reflectionUtils = reflectionUtils;
    }

    /**
     * Get the {@link ClassLoader} order.
     *
     * @return the {@link ClassLoader} order, as a pair: {@link ClassLoader},
     *         {@link ClassLoaderHandlerRegistryEntry}.
     */
    public List<Entry<ClassLoader, ClassLoaderHandlerRegistryEntry>> getClassLoaderOrder() {
        return classLoaderOrder;
    }

    /**
     * Get the all parent classloaders.
     *
     * @return all parent classloaders
     */
    public Set<ClassLoader> getAllParentClassLoaders() {
        return allParentClassLoaders;
    }

    /**
     * Find the {@link ClassLoaderHandler} that can handle a given {@link ClassLoader} instance.
     *
     * @param classLoader
     *            the {@link ClassLoader}.
     * @param log
     *            the log
     * @return the {@link ClassLoaderHandlerRegistryEntry} for the {@link ClassLoader}.
     */
    private ClassLoaderHandlerRegistryEntry getRegistryEntry(final ClassLoader classLoader, final LogNode log) {
        ClassLoaderHandlerRegistryEntry entry = classLoaderToClassLoaderHandlerRegistryEntry.get(classLoader);
        if (entry == null) {
            // Try all superclasses of classloader in turn
            for (Class<?> currClassLoaderClass = classLoader.getClass(); // 
                    currClassLoaderClass != Object.class && currClassLoaderClass != null; //
                    currClassLoaderClass = currClassLoaderClass.getSuperclass()) {
                // Find a ClassLoaderHandler that can handle the ClassLoader
                for (final ClassLoaderHandlerRegistryEntry ent : ClassLoaderHandlerRegistry.CLASS_LOADER_HANDLERS) {
                    if (ent.canHandle(currClassLoaderClass, log)) {
                        // This ClassLoaderHandler can handle the ClassLoader class, or one of its superclasses
                        entry = ent;
                        break;
                    }
                }
                if (entry != null) {
                    // Don't iterate to next superclass if a matching ClassLoaderHandler was found
                    break;
                }
            }
            if (entry == null) {
                // Use fallback handler
                entry = ClassLoaderHandlerRegistry.FALLBACK_HANDLER;
            }
            classLoaderToClassLoaderHandlerRegistryEntry.put(classLoader, entry);
        }
        return entry;
    }

    /**
     * Add a {@link ClassLoader} to the ClassLoader order at the current position.
     *
     * @param classLoader
     *            the class loader
     * @param log
     *            the log
     */
    public void add(final ClassLoader classLoader, final LogNode log) {
        if (classLoader == null) {
            return;
        }
        if (added.add(classLoader)) {
            final ClassLoaderHandlerRegistryEntry entry = getRegistryEntry(classLoader, log);
            if (entry != null) {
                classLoaderOrder.add(new SimpleEntry<>(classLoader, entry));
            }
        }
    }

    /**
     * Recursively delegate to another {@link ClassLoader}.
     *
     * @param classLoader
     *            the class loader
     * @param isParent
     *            true if this is a parent of another classloader
     * @param log
     *            the log
     */
    public void delegateTo(final ClassLoader classLoader, final boolean isParent, final LogNode log) {<FILL_FUNCTION_BODY>}
}

        if (classLoader == null) {
            return;
        }
        // Check if this is a parent before checking if the classloader is already in the delegatedTo set,
        // so that if the classloader is a context classloader but also a parent, it still gets marked as
        // a parent classloader.
        if (isParent) {
            allParentClassLoaders.add(classLoader);
        }
        // Don't delegate to a classloader twice
        if (delegatedTo.add(classLoader)) {
            // Find ClassLoaderHandlerRegistryEntry for this classloader
            final ClassLoaderHandlerRegistryEntry entry = getRegistryEntry(classLoader, log);
            // Delegate to this classloader, by recursing to that classloader to get its classloader order
            entry.findClassLoaderOrder(classLoader, this, log);
        }
    
<no_super_class>