Search in sources :

Example 46 with OnClassLoadEvent

use of org.hotswap.agent.annotation.OnClassLoadEvent in project HotswapAgent by HotswapProjects.

the class ELResolverPlugin method beanELResolverRegisterVariable.

/**
 * Hook on BeanELResolver class and for each instance:
 * - ensure plugin is initialized
 * - register instances using registerBeanELResolver() method
 */
@OnClassLoadEvent(classNameRegexp = "javax.el.BeanELResolver")
public static void beanELResolverRegisterVariable(CtClass ctClass) throws CannotCompileException {
    String initPlugin = PluginManagerInvoker.buildInitializePlugin(ELResolverPlugin.class);
    String registerThis = PluginManagerInvoker.buildCallPluginMethod(ELResolverPlugin.class, "registerBeanELResolver", "this", "java.lang.Object");
    for (CtConstructor constructor : ctClass.getDeclaredConstructors()) {
        constructor.insertAfter(initPlugin);
        constructor.insertAfter(registerThis);
    }
    boolean found = false;
    if (checkJuelEL(ctClass)) {
        found = true;
        LOGGER.debug("JuelEL - javax.el.BeanELResolver - method added " + PURGE_CLASS_CACHE_METHOD_NAME + "(java.lang.ClassLoader classLoader). ");
    } else if (checkApacheEL(ctClass)) {
        found = true;
        LOGGER.debug("ApacheEL - javax.el.BeanELResolver - method added " + PURGE_CLASS_CACHE_METHOD_NAME + "(java.lang.ClassLoader classLoader). ");
    } else if (checkJBoss_3_0_EL(ctClass)) {
        found = true;
        LOGGER.debug("JBossEL 3.0 - javax.el.BeanELResolver - method added " + PURGE_CLASS_CACHE_METHOD_NAME + "(java.lang.ClassLoader classLoader). ");
    }
    if (!found) {
        LOGGER.warning("Unable to add javax.el.BeanELResolver." + PURGE_CLASS_CACHE_METHOD_NAME + "() method. Purging will not be available.");
    }
}
Also used : CtConstructor(org.hotswap.agent.javassist.CtConstructor) OnClassLoadEvent(org.hotswap.agent.annotation.OnClassLoadEvent)

Example 47 with OnClassLoadEvent

use of org.hotswap.agent.annotation.OnClassLoadEvent in project HotswapAgent by HotswapProjects.

the class PluginClassFileTransformer method transform.

/**
 * Transformation callback as registered in initMethod:
 * hotswapTransformer.registerTransformer(). Resolve method parameters to
 * actual values, provide convenience parameters of javassist to streamline
 * the transformation.
 */
private static byte[] transform(PluginManager pluginManager, PluginAnnotation<OnClassLoadEvent> pluginAnnotation, ClassLoader classLoader, String className, Class<?> redefiningClass, ProtectionDomain protectionDomain, byte[] bytes) {
    LOGGER.trace("Transforming.... '{}' using: '{}'", className, pluginAnnotation);
    // skip synthetic classes
    if (pluginAnnotation.getAnnotation().skipSynthetic()) {
        if (isSyntheticClass(className) || (redefiningClass != null && redefiningClass.isSynthetic())) {
            return bytes;
        }
    }
    // skip anonymous class
    if (pluginAnnotation.getAnnotation().skipAnonymous()) {
        if (className.matches("\\$\\d+$")) {
            return bytes;
        }
    }
    // ensure classloader initiated
    if (classLoader != null) {
        pluginManager.initClassLoader(classLoader, protectionDomain);
    }
    // default result
    byte[] result = bytes;
    // we may need to crate CtClass on behalf of the client and close it
    // after invocation.
    CtClass ctClass = null;
    List<Object> args = new ArrayList<Object>();
    for (Class<?> type : pluginAnnotation.getMethod().getParameterTypes()) {
        if (type.isAssignableFrom(ClassLoader.class)) {
            args.add(classLoader);
        } else if (type.isAssignableFrom(String.class)) {
            args.add(className);
        } else if (type.isAssignableFrom(Class.class)) {
            args.add(redefiningClass);
        } else if (type.isAssignableFrom(ProtectionDomain.class)) {
            args.add(protectionDomain);
        } else if (type.isAssignableFrom(byte[].class)) {
            args.add(bytes);
        } else if (type.isAssignableFrom(ClassPool.class)) {
            ClassPool classPool = new ClassPool();
            classPool.appendSystemPath();
            LOGGER.trace("Adding loader classpath " + classLoader);
            classPool.appendClassPath(new LoaderClassPath(classLoader));
            args.add(classPool);
        } else if (type.isAssignableFrom(CtClass.class)) {
            try {
                ctClass = createCtClass(bytes, classLoader);
                args.add(ctClass);
            } catch (IOException e) {
                LOGGER.error("Unable create CtClass for '" + className + "'.", e);
                return result;
            }
        } else if (type.isAssignableFrom(LoadEvent.class)) {
            args.add(redefiningClass == null ? LoadEvent.DEFINE : LoadEvent.REDEFINE);
        } else if (type.isAssignableFrom(AppClassLoaderExecutor.class)) {
            args.add(new AppClassLoaderExecutor(classLoader, protectionDomain));
        } else {
            LOGGER.error("Unable to call init method on plugin '" + pluginAnnotation.getPluginClass() + "'." + " Method parameter type '" + type + "' is not recognized for @Init annotation.");
            return result;
        }
    }
    try {
        // call method on plugin (or if plugin null -> static method)
        Object resultObject = pluginAnnotation.getMethod().invoke(pluginAnnotation.getPlugin(), args.toArray());
        if (resultObject == null) {
        // Ok, nothing has changed
        } else if (resultObject instanceof byte[]) {
            result = (byte[]) resultObject;
        } else if (resultObject instanceof CtClass) {
            result = ((CtClass) resultObject).toBytecode();
            // instance than we created (it is closed elsewhere)
            if (resultObject != ctClass) {
                ((CtClass) resultObject).detach();
            }
        } else {
            LOGGER.error("Unknown result of @OnClassLoadEvent method '" + result.getClass().getName() + "'.");
        }
        // close CtClass if created from here
        if (ctClass != null) {
            // if result not set from the method, use class
            if (resultObject == null) {
                result = ctClass.toBytecode();
            }
            ctClass.detach();
        }
    } catch (IllegalAccessException e) {
        LOGGER.error("IllegalAccessException in transform method on plugin '" + pluginAnnotation.getPluginClass() + "' class '" + className + "'.", e);
    } catch (InvocationTargetException e) {
        LOGGER.error("InvocationTargetException in transform method on plugin '" + pluginAnnotation.getPluginClass() + "' class '" + className + "'.", e);
    } catch (CannotCompileException e) {
        LOGGER.error("Cannot compile class after manipulation on plugin '" + pluginAnnotation.getPluginClass() + "' class '" + className + "'.", e);
    } catch (IOException e) {
        LOGGER.error("IOException in transform method on plugin '" + pluginAnnotation.getPluginClass() + "' class '" + className + "'.", e);
    }
    return result;
}
Also used : ProtectionDomain(java.security.ProtectionDomain) LoadEvent(org.hotswap.agent.annotation.LoadEvent) OnClassLoadEvent(org.hotswap.agent.annotation.OnClassLoadEvent) ArrayList(java.util.ArrayList) ClassPool(org.hotswap.agent.javassist.ClassPool) LoaderClassPath(org.hotswap.agent.javassist.LoaderClassPath) IOException(java.io.IOException) CannotCompileException(org.hotswap.agent.javassist.CannotCompileException) InvocationTargetException(java.lang.reflect.InvocationTargetException) CtClass(org.hotswap.agent.javassist.CtClass) AppClassLoaderExecutor(org.hotswap.agent.util.AppClassLoaderExecutor)

Example 48 with OnClassLoadEvent

use of org.hotswap.agent.annotation.OnClassLoadEvent in project HotswapAgent by HotswapProjects.

the class AbstractClassBeanTransformer method transformAbstractClassBean.

/**
 * @param ctClass
 * @param classPool
 * @throws NotFoundException
 * @throws CannotCompileException
 */
@OnClassLoadEvent(classNameRegexp = "org.jboss.weld.bean.AbstractClassBean")
public static void transformAbstractClassBean(CtClass ctClass, ClassPool classPool) throws NotFoundException, CannotCompileException {
    CtMethod method = ctClass.getDeclaredMethod("cleanupAfterBoot");
    method.setBody("{ }");
    LOGGER.debug("AbstractClassBean.cleanupAfterBoot patched");
}
Also used : CtMethod(org.hotswap.agent.javassist.CtMethod) OnClassLoadEvent(org.hotswap.agent.annotation.OnClassLoadEvent)

Example 49 with OnClassLoadEvent

use of org.hotswap.agent.annotation.OnClassLoadEvent in project HotswapAgent by HotswapProjects.

the class BeanDeploymentArchiveTransformer method transform.

/**
 * Basic WeldBeanDeploymentArchive transformation.
 *
 * @param clazz
 * @param classPool
 * @throws NotFoundException
 * @throws CannotCompileException
 */
@OnClassLoadEvent(classNameRegexp = "org.jboss.weld.environment.deployment.WeldBeanDeploymentArchive")
public static void transform(CtClass clazz, ClassPool classPool) throws NotFoundException, CannotCompileException {
    CtClass[] constructorParams = new CtClass[] { classPool.get("java.lang.String"), classPool.get("java.util.Collection"), classPool.get("org.jboss.weld.bootstrap.spi.BeansXml"), classPool.get("java.util.Set") };
    StringBuilder src = new StringBuilder("{");
    src.append(PluginManagerInvoker.buildInitializePlugin(WeldPlugin.class));
    src.append(PluginManagerInvoker.buildCallPluginMethod(WeldPlugin.class, "init"));
    src.append("org.hotswap.agent.plugin.weld.command.BeanClassRefreshAgent.registerArchive(getClass().getClassLoader(), this, null);");
    src.append("}");
    CtConstructor declaredConstructor = clazz.getDeclaredConstructor(constructorParams);
    declaredConstructor.insertAfter(src.toString());
    LOGGER.debug("Class '{}' patched with BDA registration.", clazz.getName());
}
Also used : CtClass(org.hotswap.agent.javassist.CtClass) WeldPlugin(org.hotswap.agent.plugin.weld.WeldPlugin) CtConstructor(org.hotswap.agent.javassist.CtConstructor) OnClassLoadEvent(org.hotswap.agent.annotation.OnClassLoadEvent)

Example 50 with OnClassLoadEvent

use of org.hotswap.agent.annotation.OnClassLoadEvent in project HotswapAgent by HotswapProjects.

the class CdiContextsTransformer method transformReloadingWeldContexts.

/**
 * Add context reloading functionality to base contexts classes.
 *
 * @param ctClass the class
 * @param classPool the class pool
 * @throws NotFoundException the not found exception
 * @throws CannotCompileException the cannot compile exception
 */
@OnClassLoadEvent(classNameRegexp = "(org.jboss.weld.context.AbstractManagedContext)|" + "(org.jboss.weld.context.AbstractSharedContext)|" + "(org.jboss.weld.context.unbound.DependentContextImpl)|" + "(org.jboss.weld.util.ForwardingContext)|" + "(org.apache.myfaces.flow.cdi.FlowScopedContextImpl)|" + "(org.apache.myfaces.cdi.view.ViewScopeContextImpl)")
public static void transformReloadingWeldContexts(CtClass ctClass, ClassPool classPool) throws NotFoundException, CannotCompileException {
    LOGGER.debug("Adding interface {} to {}.", WeldHotswapContext.class.getName(), ctClass.getName());
    ctClass.addInterface(classPool.get(WeldHotswapContext.class.getName()));
    CtField toReloadFld = CtField.make("public transient java.util.Set $$ha$toReloadWeld = null;", ctClass);
    ctClass.addField(toReloadFld);
    CtField reloadingFld = CtField.make("public transient boolean $$ha$reloadingWeld = false;", ctClass);
    ctClass.addField(reloadingFld);
    CtMethod addBeanToReload = CtMethod.make("public void $$ha$addBeanToReloadWeld(javax.enterprise.context.spi.Contextual bean) {" + "if ($$ha$toReloadWeld == null)" + "$$ha$toReloadWeld = new java.util.HashSet();" + "$$ha$toReloadWeld.add(bean);" + "}", ctClass);
    ctClass.addMethod(addBeanToReload);
    CtMethod getBeansToReload = CtMethod.make("public java.util.Set $$ha$getBeansToReloadWeld(){return $$ha$toReloadWeld;}", ctClass);
    ctClass.addMethod(getBeansToReload);
    CtMethod reload = CtMethod.make("public void $$ha$reloadWeld() {" + ContextualReloadHelper.class.getName() + ".reload(this);}", ctClass);
    ctClass.addMethod(reload);
    CtMethod isActive = ctClass.getDeclaredMethod("isActive");
    isActive.insertAfter("{" + "if($_ && !$$ha$reloadingWeld ) { " + "$$ha$reloadingWeld = true;" + "$$ha$reloadWeld();" + "$$ha$reloadingWeld = false;" + "}" + "return $_;" + "}");
    LOGGER.debug("Class '{}' patched with hot-swapping support", ctClass.getName());
}
Also used : ContextualReloadHelper(org.hotswap.agent.plugin.weld.beans.ContextualReloadHelper) CtField(org.hotswap.agent.javassist.CtField) WeldHotswapContext(org.hotswap.agent.plugin.weld.beans.WeldHotswapContext) CtMethod(org.hotswap.agent.javassist.CtMethod) OnClassLoadEvent(org.hotswap.agent.annotation.OnClassLoadEvent)

Aggregations

OnClassLoadEvent (org.hotswap.agent.annotation.OnClassLoadEvent)50 CtMethod (org.hotswap.agent.javassist.CtMethod)29 CtConstructor (org.hotswap.agent.javassist.CtConstructor)16 CtClass (org.hotswap.agent.javassist.CtClass)13 CtField (org.hotswap.agent.javassist.CtField)10 NotFoundException (org.hotswap.agent.javassist.NotFoundException)10 CannotCompileException (org.hotswap.agent.javassist.CannotCompileException)9 ExprEditor (org.hotswap.agent.javassist.expr.ExprEditor)5 IOException (java.io.IOException)4 WeldPlugin (org.hotswap.agent.plugin.weld.WeldPlugin)4 Method (java.lang.reflect.Method)3 MalformedURLException (java.net.MalformedURLException)3 URISyntaxException (java.net.URISyntaxException)3 MethodCall (org.hotswap.agent.javassist.expr.MethodCall)3 URL (java.net.URL)2 Set (java.util.Set)2 DeltaSpikePlugin (org.hotswap.agent.plugin.deltaspike.DeltaSpikePlugin)2 ClassFileTransformer (java.lang.instrument.ClassFileTransformer)1 Field (java.lang.reflect.Field)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1