package org.hotswap.agent.plugin.owb.beans; import java.lang.reflect.Field; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.enterprise.context.spi.Context; import javax.enterprise.context.spi.Contextual; import org.apache.webbeans.component.ManagedBean; import org.apache.webbeans.context.creational.CreationalContextImpl; import org.hotswap.agent.logging.AgentLogger; /** * The Class ContextualReloadHelper. * * @author alpapad@gmail.com */ public class ContextualReloadHelper { private static AgentLogger LOGGER = AgentLogger.getLogger(ContextualReloadHelper.class); public static void reload(OwbHotswapContext ctx) { Set<Contextual<Object>> beans = ctx.__getBeansToReloadOwb(); if (beans != null && !beans.isEmpty()) { LOGGER.debug("Starting re-loading Contextuals in {}, {}", ctx, beans.size()); Iterator<Contextual<Object>> it = beans.iterator(); while (it.hasNext()) { Contextual<Object> managedBean = it.next(); destroy(ctx, managedBean); } beans.clear(); LOGGER.debug("Finished re-loading Contextuals in {}", ctx); } } /** * Tries to add the bean in the context so it is reloaded in the next activation of the context. * * @param ctx * @param managedBean * @return */ @SuppressWarnings("unchecked") public static boolean addToReloadSet(Context ctx, Contextual<?> managedBean) { try { LOGGER.debug("Adding bean in '{}' : {}", ctx.getClass(), managedBean); Field toRedefine = ctx.getClass().getField("__toReloadOwb"); Set toReload = Set.class.cast(toRedefine.get(ctx)); if (toReload == null) { toReload = new HashSet(); toRedefine.set(ctx, toReload); } toReload.add(managedBean); return true; } catch(Exception e) { LOGGER.warning("Context {} is not patched. Can not add {} to reload set", e, ctx, managedBean); } return false; } /** * Will remove bean from context forcing a clean new instance to be created (eg calling post-construct) * * @param ctx * @param managedBean */ static void destroy(OwbHotswapContext ctx, Contextual<?> managedBean ) { try { LOGGER.debug("Removing Contextual from Context........ {},: {}", managedBean, ctx); Object get = ctx.get(managedBean); if (get != null) { ctx.destroy(managedBean); } get = ctx.get(managedBean); if (get != null) { LOGGER.error("Error removing ManagedBean {}, it still exists as instance {} ", managedBean, get); ctx.destroy(managedBean); } } catch (Exception e) { LOGGER.error("Error destoying bean {},: {}", e, managedBean, ctx); } } /** * Will re-inject any managed beans in the target. Will not call any other life-cycle methods * * @param ctx * @param managedBean */ @SuppressWarnings("unchecked") static void reinitialize(Context ctx, Contextual<Object> contextual) { try { ManagedBean<Object> managedBean = ManagedBean.class.cast(contextual); LOGGER.debug("Re-Initializing........ {},: {}", managedBean, ctx); Object get = ctx.get(managedBean); if (get != null) { LOGGER.debug("Bean injection points are reinitialized '{}'", managedBean); CreationalContextImpl<Object> creationalContext = managedBean.getWebBeansContext().getCreationalContextFactory().getCreationalContext(managedBean); managedBean.getProducer().inject(get, creationalContext); } } catch (Exception e) { LOGGER.error("Error reinitializing bean {},: {}", e, contextual, ctx); } } }