package org.hotswap.agent.plugin.owb.command;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import javax.enterprise.inject.spi.Bean;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.proxy.NormalScopeProxyFactory;
import org.hotswap.agent.logging.AgentLogger;
import org.hotswap.agent.plugin.owb.OwbClassSignatureHelper;
import org.hotswap.agent.util.ReflectionHelper;
/**
* The Class ProxyRefreshAgent.
*
* @author Vladimir Dvorak
*/
public class ProxyRefreshAgent {
private static AgentLogger LOGGER = AgentLogger.getLogger(ProxyRefreshAgent.class);
/**
* Recreate proxy classes, Called from BeanClassRefreshCommand.
*
* @param appClassLoader the application class loader
* @param beanClassName the bean class name
* @param oldSignatureForProxyCheck the old signature for proxy check
* @throws IOException error working with classDefinition
*/
public static void recreateProxy(ClassLoader appClassLoader, String beanClassName, String oldSignatureForProxyCheck) throws IOException {
try {
Class<?> beanClass = appClassLoader.loadClass(beanClassName);
if (oldSignatureForProxyCheck != null) {
String newClassSignature = OwbClassSignatureHelper.getSignatureForProxyClass(beanClass);
if (newClassSignature != null && !newClassSignature.equals(oldSignatureForProxyCheck)) {
doRecreateProxy(appClassLoader, beanClass);
}
}
} catch (ClassNotFoundException e) {
LOGGER.error("Bean class not found.", e);
}
}
private static void doRecreateProxy(ClassLoader appClassLoader, Class<?> beanClass) {
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
ProxyClassLoadingDelegate.beginProxyRegeneration();
Thread.currentThread().setContextClassLoader(appClassLoader);
WebBeansContext wbc = WebBeansContext.currentInstance();
NormalScopeProxyFactory proxyFactory = wbc.getNormalScopeProxyFactory();
// Clear proxy class cache
Map cachedProxyClasses = (Map) ReflectionHelper.get(proxyFactory, "cachedProxyClasses");
Set<Bean<?>> beans = wbc.getBeanManagerImpl().getBeans(beanClass);
if (beans != null) {
boolean recreateIt = false;
for (Bean<?> bean : beans) {
if (cachedProxyClasses.containsKey(bean)) {
cachedProxyClasses.remove(bean);
recreateIt = true;
}
}
if (recreateIt) {
proxyFactory.createProxyClass(appClassLoader, beanClass);
}
}
} catch (Exception e) {
LOGGER.error("Proxy redefinition failed {}.", e, e.getMessage());
} finally {
Thread.currentThread().setContextClassLoader(oldContextClassLoader);
ProxyClassLoadingDelegate.endProxyRegeneration();
}
}
}