package org.hotswap.agent.plugin.hotswapper;
import org.hotswap.agent.config.PluginManager;
import org.hotswap.agent.javassist.ClassPool;
import org.hotswap.agent.javassist.CtClass;
import org.hotswap.agent.javassist.LoaderClassPath;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by bubnik on 22.5.2014.
*/
public class HotSwapper {
/**
* Swap class definition from another class file.
* <p/>
* This is mainly useful for unit testing - declare multiple version of a class and then
* hotswap definition and do the tests.
*
* @param original original class currently in use
* @param swap fully qualified class name of class to swap
* @throws Exception swap exception
*/
public static void swapClasses(Class original, String swap) throws Exception {
// need to recreate classpool on each swap to avoid stale class definition
ClassPool classPool = new ClassPool();
classPool.appendClassPath(new LoaderClassPath(original.getClassLoader()));
CtClass ctClass = classPool.getAndRename(swap, original.getName());
reload(original, ctClass.toBytecode());
}
private static void reload(Class original, byte[] bytes) {
Map<Class<?>, byte[]> reloadMap = new HashMap<Class<?>, byte[]>();
reloadMap.put(original, bytes);
PluginManager.getInstance().hotswap(reloadMap);
}
public static Class newClass(String className, String directory, ClassLoader cl){
try {
ClassPool classPool = new ClassPool();
classPool.appendClassPath(new LoaderClassPath(cl));
CtClass makeClass = classPool.makeClass(className);
makeClass.writeFile(directory);
return makeClass.toClass();
} catch (Throwable ex) {
Logger.getLogger(HotSwapper.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
}
}
}