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

mockit.internal.state.CachedClassfiles Maven / Gradle / Ivy

Go to download

JMockit is a Java toolkit for developer (unit/integration) testing. It contains mocking APIs and other tools, 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.

There is a newer version: 1.7
Show newest version
/*
 * Copyright (c) 2006-2013 Rogério Liesenfeld
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
 */
package mockit.internal.state;

import java.lang.instrument.*;
import java.security.*;
import java.util.*;

/**
 * Holds a map of internal class names to the corresponding class files (bytecode arrays), for the classes
 * that have already been loaded during the test run.
 * These classfiles are not necessarily the same as those stored in the corresponding ".class" files
 * available from the runtime classpath.
 * If any third-party {@link java.lang.instrument.ClassFileTransformer}s are active, those original classfiles
 * may have been modified before being loaded by the JVM.
 * JMockit installs a {@code ClassFileTransformer} of its own which saves all potentially modified classfiles
 * here.
 * 

* This bytecode cache allows classes to be mocked and un-mocked correctly, even in the presence of other * bytecode modification agents such as the AspectJ load-time weaver. */ public final class CachedClassfiles implements ClassFileTransformer { public static final CachedClassfiles INSTANCE = new CachedClassfiles(); private final Map> classLoadersAndClassfiles = new IdentityHashMap>(2); private ClassDefinition[] classesBeingMocked; public void setClassesBeingMocked(ClassDefinition[] classDefs) { classesBeingMocked = classDefs; } private CachedClassfiles() {} public byte[] transform( ClassLoader loader, String classDesc, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { if (classBeingRedefined == null) { // class definition if (!isExcluded(classDesc)) { addClassfile(loader, classDesc, classfileBuffer); } } else if (!isBeingMocked(classBeingRedefined) && !isExcluded(classDesc)) { // class redefinition addClassfileIfNotYetPresent(loader, classDesc, classfileBuffer); } return null; } private boolean isExcluded(String classDesc) { return classDesc.startsWith("org/junit/") || classDesc.startsWith("sun/") && !classDesc.startsWith("sun/proxy/$") || classDesc.startsWith("com/intellij/") || classDesc.startsWith("mockit/internal/") || classDesc.startsWith("mockit/integration/") || classDesc.startsWith("mockit/coverage/") || classDesc.startsWith("mockit/") && classDesc.indexOf('$') < 0; } private boolean isBeingMocked(Class classBeingRedefined) { if (classesBeingMocked != null) { for (ClassDefinition classDef : classesBeingMocked) { if (classDef.getDefinitionClass() == classBeingRedefined) { return true; } } } return false; } private synchronized void addClassfile(ClassLoader loader, String classDesc, byte[] classfile) { Map classfiles = getClassfiles(loader); classfiles.put(classDesc, classfile); } private Map getClassfiles(ClassLoader loader) { Map classfiles = classLoadersAndClassfiles.get(loader); if (classfiles == null) { classfiles = new HashMap(100); classLoadersAndClassfiles.put(loader, classfiles); } return classfiles; } private synchronized void addClassfileIfNotYetPresent(ClassLoader loader, String classDesc, byte[] classfile) { Map classfiles = getClassfiles(loader); if (!classfiles.containsKey(classDesc)) { classfiles.put(classDesc, classfile); } } private synchronized byte[] findClassfile(Class aClass) { Map classfiles = getClassfiles(aClass.getClassLoader()); return classfiles.get(aClass.getName().replace('.', '/')); } private synchronized byte[] findClassfile(ClassLoader loader, String classDesc) { Map classfiles = getClassfiles(loader); return classfiles.get(classDesc); } public static byte[] getClassfile(Class aClass) { return INSTANCE.findClassfile(aClass); } public static byte[] getClassfile(ClassLoader loader, String internalClassName) { return INSTANCE.findClassfile(loader, internalClassName); } public static void addClassfile(Class aClass, byte[] classfile) { INSTANCE.addClassfile(aClass.getClassLoader(), aClass.getName().replace('.', '/'), classfile); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy