mockit.internal.util.ClassLoad Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jmockit Show documentation
Show all versions of jmockit Show documentation
JMockit is a Java toolkit for automated developer testing.
It contains mocking/faking APIs and a code coverage tool, supporting both JUnit and TestNG.
The mocking APIs allow all kinds of Java code, without testability restrictions, to be tested
in isolation from selected dependencies.
/*
* Copyright (c) 2006 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.internal.util;
import java.util.*;
import java.util.concurrent.*;
import javax.annotation.*;
import mockit.internal.state.*;
public final class ClassLoad
{
public static final String OBJECT = "java/lang/Object";
private static final ClassLoader THIS_CL = ClassLoad.class.getClassLoader();
private static final Map> LOADED_CLASSES = new ConcurrentHashMap>();
private static final Map SUPER_CLASSES = new ConcurrentHashMap();
private ClassLoad() {}
public static void registerLoadedClass(@Nonnull Class> aClass)
{
LOADED_CLASSES.put(aClass.getName(), aClass);
}
@Nonnull
public static Class loadByInternalName(@Nonnull String internalClassName)
{
return loadClass(internalClassName.replace('/', '.'));
}
@Nonnull
public static Class loadClass(@Nonnull String className)
{
@Nullable Class> loadedClass = LOADED_CLASSES.get(className);
if (loadedClass == null) {
try {
loadedClass = loadClass(null, className);
if (loadedClass == null) {
if (className.startsWith("mockit.")) {
loadedClass = loadClass(THIS_CL, className);
}
if (loadedClass == null) {
Class> testClass = TestRun.getCurrentTestClass();
loadedClass = testClass == null ? null : loadClass(testClass.getClassLoader(), className);
if (loadedClass == null) {
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
loadedClass = loadClass(contextCL, className);
if (loadedClass == null) {
throw new IllegalArgumentException("No class with name \"" + className + "\" found");
}
}
}
}
}
catch (LinkageError e) {
e.printStackTrace();
throw e;
}
}
//noinspection unchecked
return (Class) loadedClass;
}
@Nonnull
public static Class loadClassAtStartup(@Nonnull String className)
{
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
Class> loadedClass;
try {
loadedClass = loadClass(contextCL, className);
if (loadedClass == null) {
loadedClass = loadClass(THIS_CL, className);
if (loadedClass == null) {
throw new IllegalArgumentException("No class with name \"" + className + "\" found");
}
}
}
catch (LinkageError e) {
e.printStackTrace();
throw e;
}
//noinspection unchecked
return (Class) loadedClass;
}
@Nullable
public static Class> loadClass(@Nullable ClassLoader loader, @Nonnull String className)
{
try { return Class.forName(className, true, loader); } catch (ClassNotFoundException ignore) { return null; }
}
@Nonnull
public static Class loadFromLoader(@Nullable ClassLoader loader, @Nonnull String className)
{
try {
//noinspection unchecked
return (Class) Class.forName(className, true, loader);
}
catch (ClassNotFoundException ignore) {
throw new IllegalArgumentException("No class with name \"" + className + "\" found");
}
}
@Nullable
public static Class extends T> searchTypeInClasspath(@Nonnull String typeName)
{
return searchTypeInClasspath(typeName, false);
}
@Nullable
public static Class extends T> searchTypeInClasspath(@Nonnull String typeName, boolean initializeType)
{
//noinspection OverlyBroadCatchBlock
try {
//noinspection unchecked
return (Class extends T>) Class.forName(typeName, initializeType, THIS_CL);
}
catch (Throwable ignore) { return null; }
}
public static void addSuperClass(@Nonnull String classInternalName, @Nonnull String superClassInternalName)
{
SUPER_CLASSES.put(classInternalName.intern(), superClassInternalName.intern());
}
@Nonnull
public static String getSuperClass(@Nonnull String classInternalName)
{
String classDesc = classInternalName.intern();
String superName = SUPER_CLASSES.get(classDesc);
if (superName == null) {
Class> theClass = loadByInternalName(classDesc);
Class> superClass = theClass.getSuperclass();
if (superClass != null) {
superName = superClass.getName().replace('.', '/').intern();
SUPER_CLASSES.put(classDesc, superName);
}
}
return superName == null ? OBJECT : superName;
}
@Nullable
public static String whichIsSuperClass(@Nonnull String internalClassName1, @Nonnull String internalClassName2)
{
String class1 = actualSuperClass(internalClassName1, internalClassName2);
if (class1 != null) {
return class1;
}
String class2 = actualSuperClass(internalClassName2, internalClassName1);
return class2;
}
@Nullable
private static String actualSuperClass(@Nonnull String candidateSuperClass, @Nonnull String candidateSubclass)
{
String subclass = candidateSubclass;
while (true) {
String superClass = getSuperClass(subclass);
if (superClass.equals(OBJECT)) {
return null;
}
if (superClass.equals(candidateSuperClass)) {
return candidateSuperClass;
}
subclass = superClass;
}
}
public static boolean isGeneratedSubclass(@Nonnull String className)
{
int p = className.indexOf('$') + 1;
//noinspection SimplifiableIfStatement
if (p < 2 || p == className.length() || className.charAt(p) != '$') {
return false;
}
return className.contains("_$$_javassist_") || className.contains("_$$_jvst") || className.contains("CGLIB$$");
}
public static boolean isClassLoaderWithNoDirectAccess(@Nullable ClassLoader classLoader)
{
return classLoader == null || classLoader != THIS_CL && classLoader.getParent() != THIS_CL;
}
public static ClassLoader getClassLoaderWithAccess(@Nonnull Class> classToBeAccessed)
{
ClassLoader cl = classToBeAccessed.getClassLoader();
return isClassLoaderWithNoDirectAccess(cl) ? THIS_CL : cl;
}
}