package org.hotswap.agent.plugin.spring;
import org.hotswap.agent.javassist.ClassPool;
import org.hotswap.agent.javassist.CtClass;
import org.hotswap.agent.javassist.LoaderClassPath;
import org.hotswap.agent.logging.AgentLogger;
import org.hotswap.agent.plugin.spring.signature.ClassSignatureComparer;
/**
* Determines if a full Spring reload is needed. Changes to synthetic and known generated classes are ignored. For other
* classes, changes to method bodies are ignored.
*
* @author Erki Ehtla
*
*/
public class SpringChangesAnalyzer {
private static AgentLogger LOGGER = AgentLogger.getLogger(SpringPlugin.class);
private ClassPool cp;
public SpringChangesAnalyzer(final ClassLoader classLoader) {
this.cp = new ClassPool() {
@Override
public ClassLoader getClassLoader() {
return classLoader;
}
};
cp.appendSystemPath();
cp.appendClassPath(new LoaderClassPath(classLoader));
}
public boolean isReloadNeeded(Class<?> classBeingRedefined, byte[] classfileBuffer) {
if (classBeingRedefined.isSynthetic() || isSyntheticClass(classBeingRedefined))
return false;
return classChangeNeedsReload(classBeingRedefined, classfileBuffer);
}
private boolean classChangeNeedsReload(Class<?> classBeingRedefined, byte[] classfileBuffer) {
CtClass makeClass = null;
try {
makeClass = cp.makeClass(new java.io.ByteArrayInputStream(classfileBuffer));
return ClassSignatureComparer.isPoolClassDifferent(classBeingRedefined, cp);
} catch (Exception e) {
LOGGER.error("Error analyzing class {} for reload necessity. Defaulting to yes.", e,
classBeingRedefined.getName());
} finally {
if (makeClass != null)
makeClass.detach();
}
return true;
}
protected boolean isSyntheticClass(Class<?> classBeingRedefined) {
return classBeingRedefined.getSimpleName().contains("$$_javassist")
|| classBeingRedefined.getName().startsWith("com.sun.proxy.$Proxy")
|| classBeingRedefined.getSimpleName().contains("$$Enhancer");
}
}