package ch.raffael.util.common;

import java.util.Arrays;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import ch.raffael.util.common.annotations.Utility;


/**
 * @author <a href="mailto:herzog@raffael.ch">Raffael Herzog</a>
 */
@Utility
public class Classes {

    private static final GetCallerSecurityManager GET_CALLER = new GetCallerSecurityManager();

    private Classes() {
    }

    @NotNull
    public static Class<?> callerClass(@NotNull Class<?> base) {
        return GET_CALLER.getCallerClass(base);
    }

    @NotNull
    public static ClassLoader classLoader(@Nullable ClassLoader explicit, @NotNull Class<?> fallback) {
        if ( explicit != null ) {
            return explicit;
        }
        ClassLoader thread = Thread.currentThread().getContextClassLoader();
        if ( thread != null ) {
            return thread;
        }
        return fallback.getClassLoader();
    }

    private final static class GetCallerSecurityManager extends SecurityManager {
        @SuppressWarnings({ "ForLoopReplaceableByForEach" })
        private Class<?> getCallerClass(Class<?> base) {
            Class<?>[] context = getClassContext();
            for ( int i = 0; i < context.length; i++ ) {
                if ( !context[i].equals(Classes.class) && !context[i].equals(GetCallerSecurityManager.class) && !context[i].equals(base) ) {
                    return context[i];
                }
            }
            throw new IllegalStateException("Cannot determine caller from context " + Arrays.asList(context));
        }
    }


}

@@ -616,48 +616,429 @@
 der(
-@Nullable ClassLoader explicit, @NotNull
+) %7B%0A        return classLoader(null, null);%0A    %7D%0A%0A    @NotNull%0A    public static ClassLoader classLoader(@Nullable Class fallback) %7B%0A        return classLoader(null, fallback);%0A    %7D%0A%0A    @NotNull%0A    public static ClassLoader classLoader(@Nullable ClassLoader explicit) %7B%0A        return classLoader(explicit, null);%0A    %7D%0A%0A    @NotNull%0A    public static ClassLoader classLoader(@Nullable ClassLoader explicit, @Nullable
  Cla
@@ -1229,32 +1229,32 @@
 ead != null ) %7B%0A
-
             retu
@@ -1266,32 +1266,127 @@
 read;%0A        %7D%0A
+        if ( fallback == null ) %7B%0A            fallback = callerClass(Classes.class);%0A        %7D%0A
         return f

Add more variants of classLoader().