All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mockit.internal.reflection.EmptyProxy Maven / Gradle / Ivy

/*
 * Copyright (c) 2006 JMockit developers
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
 */
package mockit.internal.reflection;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;

/**
 * This marker interface exists only to guarantee that JMockit can get the bytecode definition of each Proxy class it
 * creates through java.lang.reflect.Proxy. If such a class is created before JMockit is initialized, its
 * bytecode won't be stored in JMockit's cache. And since the JDK uses an internal cache for proxy classes, it won't
 * create a new one, therefore not going through the ProxyRegistrationTransformer. So, by always implementing this
 * additional interface, we can guarantee a new proxy class will be created when JMockit first requests it for a given
 * interface.
 */
public interface EmptyProxy {
    final class Impl {
        private Impl() {
        }

        @NonNull
        public static  E newEmptyProxy(@Nullable ClassLoader loader, @NonNull Type... interfacesToBeProxied) {
            List> interfaces = new ArrayList<>();

            for (Type type : interfacesToBeProxied) {
                addInterface(interfaces, type);
            }

            if (loader == null) {
                // noinspection AssignmentToMethodParameter
                loader = interfaces.get(0).getClassLoader();
            }

            if (loader == EmptyProxy.class.getClassLoader()) {
                interfaces.add(EmptyProxy.class);
            }

            Class[] interfacesArray = interfaces.toArray(new Class[interfaces.size()]);

            // noinspection unchecked
            return (E) Proxy.newProxyInstance(loader, interfacesArray, MockInvocationHandler.INSTANCE);
        }

        private static void addInterface(@NonNull List> interfaces, @NonNull Type type) {
            if (type instanceof Class) {
                interfaces.add((Class) type);
            } else if (type instanceof ParameterizedType) {
                ParameterizedType paramType = (ParameterizedType) type;
                interfaces.add((Class) paramType.getRawType());
            } else if (type instanceof TypeVariable) {
                TypeVariable typeVar = (TypeVariable) type;
                addBoundInterfaces(interfaces, typeVar.getBounds());
            }
        }

        private static void addBoundInterfaces(@NonNull List> interfaces, @NonNull Type[] bounds) {
            for (Type bound : bounds) {
                addInterface(interfaces, bound);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy