package org.hotswap.agent.plugin.proxy; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.hotswap.agent.command.Command; import org.hotswap.agent.command.MergeableCommand; import org.hotswap.agent.config.PluginManager; import org.hotswap.agent.logging.AgentLogger; import org.hotswap.agent.plugin.proxy.java.ProxyGenerator; /** * Joins subsequent proxy redefinition commands together and guarantee execution order */ public class ReloadJavaProxyCommand extends MergeableCommand { private static AgentLogger LOGGER = AgentLogger.getLogger(ReloadJavaProxyCommand.class); private ClassLoader classLoader; private String className; private Map<String, String> signatureMapOrig; public ReloadJavaProxyCommand(ClassLoader classLoader, String className, Map<String, String> signatureMapOrig) { this.classLoader = classLoader; this.classLoader = classLoader; this.className = className; this.className = className; this.signatureMapOrig = signatureMapOrig; } public void executeCommand() { try { executeSingleCommand(); List<Command> commands = new ArrayList<>(getMergedCommands()); for (Command command: commands) { ((ReloadJavaProxyCommand) command).executeSingleCommand(); } } finally { ProxyPlugin.reloadFlag = false; } } public void executeSingleCommand() { try { Class<?> clazz = classLoader.loadClass(className); Map<String, String> signatureMap = ProxyClassSignatureHelper.getNonSyntheticSignatureMap(clazz); if (!signatureMap.equals(signatureMapOrig)) { byte[] generateProxyClass = ProxyGenerator.generateProxyClass(className, clazz.getInterfaces()); Map<Class<?>, byte[]> reloadMap = new HashMap<Class<?>, byte[]>(); reloadMap.put(clazz, generateProxyClass); PluginManager.getInstance().hotswap(reloadMap); LOGGER.reload("Class '{}' has been reloaded.", className); } } catch (ClassNotFoundException e) { LOGGER.error("Error redefining java proxy {}", e, className); } } public boolean shiftScheduleTime() { return false; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ReloadJavaProxyCommand that = (ReloadJavaProxyCommand) o; if (!classLoader.equals(that.classLoader)) return false; return true; } @Override public int hashCode() { int result = classLoader.hashCode(); return result; } @Override public String toString() { return "ReloadJavaProxyCommand{" + "classLoader=" + classLoader + '}'; } }