Search in sources :

Example 21 with CannotCompileException

use of org.hotswap.agent.javassist.CannotCompileException in project HotswapAgent by HotswapProjects.

the class TransformNewClass method transform.

/**
 * Modifies a sequence of
 *    NEW classname
 *    DUP
 *    ...
 *    INVOKESPECIAL classname:method
 */
public int transform(CtClass clazz, int pos, CodeIterator iterator, ConstPool cp) throws CannotCompileException {
    int index;
    int c = iterator.byteAt(pos);
    if (c == NEW) {
        index = iterator.u16bitAt(pos + 1);
        if (cp.getClassInfo(index).equals(classname)) {
            if (iterator.byteAt(pos + 3) != DUP)
                throw new CannotCompileException("NEW followed by no DUP was found");
            if (newClassIndex == 0)
                newClassIndex = cp.addClassInfo(newClassName);
            iterator.write16bit(newClassIndex, pos + 1);
            ++nested;
        }
    } else if (c == INVOKESPECIAL) {
        index = iterator.u16bitAt(pos + 1);
        int typedesc = cp.isConstructor(classname, index);
        if (typedesc != 0 && nested > 0) {
            int nt = cp.getMethodrefNameAndType(index);
            if (newMethodNTIndex != nt) {
                newMethodNTIndex = nt;
                newMethodIndex = cp.addMethodrefInfo(newClassIndex, nt);
            }
            iterator.write16bit(newMethodIndex, pos + 1);
            --nested;
        }
    }
    return pos;
}
Also used : CannotCompileException(org.hotswap.agent.javassist.CannotCompileException)

Example 22 with CannotCompileException

use of org.hotswap.agent.javassist.CannotCompileException in project HotswapAgent by HotswapProjects.

the class ELResolverPlugin method patchJBossEl.

/*
     * JBossEL has weak reference cache. Values are stored in ThreadGroupContext cache, that must be flushed from appropriate thread.
     * Therefore we must create request for cleanup cache in PURGE_CLASS_CACHE_METHOD and own cleanup is executed indirectly when
     * application calls getBeanProperty(...).
     */
private static void patchJBossEl(CtClass ctClass) {
    try {
        ctClass.addField(new CtField(CtClass.booleanType, "$$ha$purgeRequested", ctClass), CtField.Initializer.constant(false));
        ctClass.addMethod(CtNewMethod.make("public void " + PURGE_CLASS_CACHE_METHOD_NAME + "(java.lang.ClassLoader classLoader) {" + "$$ha$purgeRequested=true;" + "}", ctClass));
        try {
            CtMethod mGetBeanProperty = ctClass.getDeclaredMethod("getBeanProperty");
            mGetBeanProperty.insertBefore("if($$ha$purgeRequested) {" + "$$ha$purgeRequested=false;" + "java.lang.reflect.Method meth = javax.el.BeanELResolver.SoftConcurrentHashMap.class.getDeclaredMethod(\"$$ha$createNewInstance\", null);" + "properties = (javax.el.BeanELResolver.SoftConcurrentHashMap) meth.invoke(properties, null);" + "}");
        } catch (NotFoundException e) {
            LOGGER.debug("FIXME : checkJBoss_3_0_EL() 'getBeanProperty(...)' not found in javax.el.BeanELResolver.");
        }
    } catch (CannotCompileException e) {
        LOGGER.error("patchJBossEl() exception {}", e.getMessage());
    }
}
Also used : CtField(org.hotswap.agent.javassist.CtField) NotFoundException(org.hotswap.agent.javassist.NotFoundException) CannotCompileException(org.hotswap.agent.javassist.CannotCompileException) CtMethod(org.hotswap.agent.javassist.CtMethod)

Example 23 with CannotCompileException

use of org.hotswap.agent.javassist.CannotCompileException 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)

Aggregations

CannotCompileException (org.hotswap.agent.javassist.CannotCompileException)23 CtMethod (org.hotswap.agent.javassist.CtMethod)11 NotFoundException (org.hotswap.agent.javassist.NotFoundException)9 OnClassLoadEvent (org.hotswap.agent.annotation.OnClassLoadEvent)8 CtClass (org.hotswap.agent.javassist.CtClass)7 ExprEditor (org.hotswap.agent.javassist.expr.ExprEditor)6 CtField (org.hotswap.agent.javassist.CtField)4 MethodCall (org.hotswap.agent.javassist.expr.MethodCall)4 IOException (java.io.IOException)3 Method (java.lang.reflect.Method)3 ArrayList (java.util.ArrayList)2 ClassPool (org.hotswap.agent.javassist.ClassPool)2 CtConstructor (org.hotswap.agent.javassist.CtConstructor)2 LoaderClassPath (org.hotswap.agent.javassist.LoaderClassPath)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 InputStream (java.io.InputStream)1 Field (java.lang.reflect.Field)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 ProtectionDomain (java.security.ProtectionDomain)1 LoadEvent (org.hotswap.agent.annotation.LoadEvent)1