Search in sources :

Example 11 with CtConstructor

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

the class ClassInitPlugin method patch.

@OnClassLoadEvent(classNameRegexp = ".*", events = LoadEvent.REDEFINE)
public static void patch(final CtClass ctClass, final ClassLoader classLoader, final Class<?> originalClass) throws IOException, CannotCompileException, NotFoundException {
    if (isSyntheticClass(originalClass)) {
        return;
    }
    final String className = ctClass.getName();
    try {
        CtMethod origMethod = ctClass.getDeclaredMethod(HOTSWAP_AGENT_CLINIT_METHOD);
        ctClass.removeMethod(origMethod);
    } catch (org.hotswap.agent.javassist.NotFoundException ex) {
    // swallow
    }
    CtConstructor clinit = ctClass.getClassInitializer();
    if (clinit != null) {
        LOGGER.debug("Adding __ha_clinit to class: {}", className);
        CtConstructor haClinit = new CtConstructor(clinit, ctClass, null);
        haClinit.getMethodInfo().setName(HOTSWAP_AGENT_CLINIT_METHOD);
        haClinit.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
        ctClass.addConstructor(haClinit);
        final boolean[] reinitializeStatics = new boolean[] { false };
        haClinit.instrument(new ExprEditor() {

            public void edit(FieldAccess f) throws CannotCompileException {
                try {
                    if (f.isStatic() && f.isWriter()) {
                        Field originalField = null;
                        try {
                            originalField = originalClass.getDeclaredField(f.getFieldName());
                        } catch (NoSuchFieldException e) {
                            LOGGER.debug("New field will be initialized {}", f.getFieldName());
                            reinitializeStatics[0] = true;
                        }
                        if (originalField != null) {
                            // ENUM$VALUES is last in enumeration
                            if (originalClass.isEnum() && "ENUM$VALUES".equals(f.getFieldName())) {
                                if (reinitializeStatics[0]) {
                                    LOGGER.debug("New field will be initialized {}", f.getFieldName());
                                } else {
                                    reinitializeStatics[0] = checkOldEnumValues(ctClass, originalClass);
                                }
                            } else {
                                LOGGER.debug("Skipping old field {}", f.getFieldName());
                                f.replace("{}");
                            }
                        }
                    }
                } catch (Exception e) {
                    LOGGER.error("Patching __ha_clinit method failed.", e);
                }
            }
        });
        if (reinitializeStatics[0]) {
            PluginManager.getInstance().getScheduler().scheduleCommand(new Command() {

                @Override
                public void executeCommand() {
                    try {
                        Class<?> clazz = classLoader.loadClass(className);
                        Method m = clazz.getDeclaredMethod(HOTSWAP_AGENT_CLINIT_METHOD, new Class[] {});
                        if (m != null) {
                            m.invoke(null, new Object[] {});
                        }
                    } catch (Exception e) {
                        LOGGER.error("Error initializing redefined class {}", e, className);
                    } finally {
                        reloadFlag = false;
                    }
                }
            }, // Hack : init should be done after dependant class redefinition. Since the class can
            150);
        // be proxied by syntetic proxy, the class init must be scheduled after proxy redefinition.
        // Currently proxy redefinition (in ProxyPlugin) is scheduled with 100ms delay, therefore
        // the class init must be scheduled after it.
        } else {
            reloadFlag = false;
        }
    }
}
Also used : CannotCompileException(org.hotswap.agent.javassist.CannotCompileException) CtMethod(org.hotswap.agent.javassist.CtMethod) Method(java.lang.reflect.Method) CannotCompileException(org.hotswap.agent.javassist.CannotCompileException) IOException(java.io.IOException) NotFoundException(org.hotswap.agent.javassist.NotFoundException) CtConstructor(org.hotswap.agent.javassist.CtConstructor) Field(java.lang.reflect.Field) CtField(org.hotswap.agent.javassist.CtField) Command(org.hotswap.agent.command.Command) NotFoundException(org.hotswap.agent.javassist.NotFoundException) ExprEditor(org.hotswap.agent.javassist.expr.ExprEditor) CtClass(org.hotswap.agent.javassist.CtClass) FieldAccess(org.hotswap.agent.javassist.expr.FieldAccess) CtMethod(org.hotswap.agent.javassist.CtMethod) OnClassLoadEvent(org.hotswap.agent.annotation.OnClassLoadEvent)

Example 12 with CtConstructor

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

the class CtClassSignature method getValue.

@Override
public String getValue() throws Exception {
    List<String> strings = new ArrayList<>();
    if (hasElement(ClassSignatureElement.METHOD)) {
        boolean usePrivateMethod = hasElement(ClassSignatureElement.METHOD_PRIVATE);
        boolean useStaticMethod = hasElement(ClassSignatureElement.METHOD_STATIC);
        for (CtMethod method : ctClass.getDeclaredMethods()) {
            if (!usePrivateMethod && Modifier.isPrivate(method.getModifiers()))
                continue;
            if (!useStaticMethod && Modifier.isStatic(method.getModifiers()))
                continue;
            strings.add(getMethodString(method));
        }
    }
    if (hasElement(ClassSignatureElement.CONSTRUCTOR)) {
        boolean usePrivateConstructor = hasElement(ClassSignatureElement.CONSTRUCTOR_PRIVATE);
        for (CtConstructor method : ctClass.getDeclaredConstructors()) {
            if (!usePrivateConstructor && Modifier.isPrivate(method.getModifiers()))
                continue;
            strings.add(getConstructorString(method));
        }
    }
    if (hasElement(ClassSignatureElement.CLASS_ANNOTATION)) {
        strings.add(annotationToString(ctClass.getAvailableAnnotations()));
    }
    if (hasElement(ClassSignatureElement.INTERFACES)) {
        for (CtClass iClass : ctClass.getInterfaces()) {
            strings.add(iClass.getName());
        }
    }
    if (hasElement(ClassSignatureElement.SUPER_CLASS)) {
        if (ctClass.getSuperclass() != null && !ctClass.getSuperclass().getName().equals(Object.class.getName()))
            strings.add(ctClass.getSuperclass().getName());
    }
    if (hasElement(ClassSignatureElement.FIELD)) {
        boolean useStaticField = hasElement(ClassSignatureElement.FIELD_STATIC);
        boolean useFieldAnnotation = hasElement(ClassSignatureElement.FIELD_ANNOTATION);
        for (CtField field : ctClass.getDeclaredFields()) {
            if (!useStaticField && Modifier.isStatic(field.getModifiers()))
                continue;
            String fieldSignature = field.getType().getName() + " " + field.getName();
            if (useFieldAnnotation) {
                fieldSignature += annotationToString(field.getAvailableAnnotations());
            }
            strings.add(fieldSignature + ";");
        }
    }
    Collections.sort(strings);
    StringBuilder strBuilder = new StringBuilder();
    for (String methodString : strings) {
        strBuilder.append(methodString);
    }
    return strBuilder.toString();
}
Also used : CtClass(org.hotswap.agent.javassist.CtClass) CtField(org.hotswap.agent.javassist.CtField) ArrayList(java.util.ArrayList) CtMethod(org.hotswap.agent.javassist.CtMethod) CtConstructor(org.hotswap.agent.javassist.CtConstructor)

Example 13 with CtConstructor

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

the class WebappLoaderTransformer method patchStandardRoot.

/**
 * Resource lookup for Tomcat 8x.
 *
 * Before the resource is handled by Tomcat, try to get extraResource handled by the plugin.
 */
@OnClassLoadEvent(classNameRegexp = "org.apache.catalina.webresources.StandardRoot")
public static void patchStandardRoot(ClassPool classPool, CtClass ctClass) throws NotFoundException, CannotCompileException, ClassNotFoundException {
    CtClass ctFileResource = classPool.get("org.apache.catalina.webresources.FileResource");
    CtConstructor ctFileResourceConstructor = ctFileResource.getConstructors()[0];
    CtClass[] constructorTypes = ctFileResourceConstructor.getParameterTypes();
    String constrParams;
    if (constructorTypes.length == 4)
        constrParams = "this, path, file, false";
    else if (constructorTypes.length == 5)
        constrParams = "this, path, file, false, null";
    else {
        LOGGER.warning("org.apache.catalina.webresources.FileResource unknown constructor. Tomcat plugin will not work properly.");
        return;
    }
    try {
        ctClass.getDeclaredMethod("getResourceInternal", new CtClass[] { classPool.get(String.class.getName()), CtPrimitiveType.booleanType }).insertBefore("java.io.File file = " + TomcatPlugin.class.getName() + ".getExtraResourceFile(this, path);" + "if (file != null) return new org.apache.catalina.webresources.FileResource(" + constrParams + ");");
    } catch (NotFoundException e) {
        LOGGER.warning("org.apache.catalina.webresources.StandardRoot does not contain getResourceInternal method. Tomcat plugin will not work properly.");
        return;
    }
    // if getResources() should contain extraClasspath, expand the original returned array and prepend extraClasspath result
    try {
        ctClass.getDeclaredMethod("getResources", new CtClass[] { classPool.get(String.class.getName()), CtPrimitiveType.booleanType }).insertAfter("java.io.File file = " + TomcatPlugin.class.getName() + ".getExtraResourceFile(this, path);" + "if (file != null) {" + "org.apache.catalina.WebResource[] ret = new org.apache.catalina.WebResource[$_.length + 1];" + "ret[0] = new org.apache.catalina.webresources.FileResource(" + constrParams + ");" + "java.lang.System.arraycopy($_, 0, ret, 1, $_.length);" + "return ret;" + "} else {return $_;}");
    } catch (NotFoundException e) {
        LOGGER.warning("org.apache.catalina.webresources.StandardRoot does not contain getResourceInternal method. Tomcat plugin will not work properly.");
        return;
    }
}
Also used : CtClass(org.hotswap.agent.javassist.CtClass) NotFoundException(org.hotswap.agent.javassist.NotFoundException) CtConstructor(org.hotswap.agent.javassist.CtConstructor) OnClassLoadEvent(org.hotswap.agent.annotation.OnClassLoadEvent)

Example 14 with CtConstructor

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

the class Javac method compileBody.

/**
 * Compiles a method (or constructor) body.
 *
 * @param src	a single statement or a block.
 *              If null, this method produces a body returning zero or null.
 */
public Bytecode compileBody(CtBehavior method, String src) throws CompileError {
    try {
        int mod = method.getModifiers();
        recordParams(method.getParameterTypes(), Modifier.isStatic(mod));
        CtClass rtype;
        if (method instanceof CtMethod) {
            gen.setThisMethod((CtMethod) method);
            rtype = ((CtMethod) method).getReturnType();
        } else
            rtype = CtClass.voidType;
        recordReturnType(rtype, false);
        boolean isVoid = rtype == CtClass.voidType;
        if (src == null)
            makeDefaultBody(bytecode, rtype);
        else {
            Parser p = new Parser(new Lex(src));
            SymbolTable stb = new SymbolTable(stable);
            Stmnt s = p.parseStatement(stb);
            if (p.hasMore())
                throw new CompileError("the method/constructor body must be surrounded by {}");
            boolean callSuper = false;
            if (method instanceof CtConstructor)
                callSuper = !((CtConstructor) method).isClassInitializer();
            gen.atMethodBody(s, callSuper, isVoid);
        }
        return bytecode;
    } catch (NotFoundException e) {
        throw new CompileError(e.toString());
    }
}
Also used : CtClass(org.hotswap.agent.javassist.CtClass) NotFoundException(org.hotswap.agent.javassist.NotFoundException) CtMethod(org.hotswap.agent.javassist.CtMethod) CtConstructor(org.hotswap.agent.javassist.CtConstructor)

Example 15 with CtConstructor

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

the class Expr method where.

/**
 * Returns the constructor or method containing the expression.
 */
public CtBehavior where() {
    MethodInfo mi = thisMethod;
    CtBehavior[] cb = thisClass.getDeclaredBehaviors();
    for (int i = cb.length - 1; i >= 0; --i) if (cb[i].getMethodInfo2() == mi)
        return cb[i];
    CtConstructor init = thisClass.getClassInitializer();
    if (init != null && init.getMethodInfo2() == mi)
        return init;
    /* getDeclaredBehaviors() returns a list of methods/constructors.
         * Although the list is cached in a CtClass object, it might be
         * recreated for some reason.  Thus, the member name and the signature
         * must be also checked.
         */
    for (int i = cb.length - 1; i >= 0; --i) {
        if (thisMethod.getName().equals(cb[i].getMethodInfo2().getName()) && thisMethod.getDescriptor().equals(cb[i].getMethodInfo2().getDescriptor())) {
            return cb[i];
        }
    }
    throw new RuntimeException("fatal: not found");
}
Also used : CtBehavior(org.hotswap.agent.javassist.CtBehavior) MethodInfo(org.hotswap.agent.javassist.bytecode.MethodInfo) CtConstructor(org.hotswap.agent.javassist.CtConstructor)

Aggregations

CtConstructor (org.hotswap.agent.javassist.CtConstructor)21 OnClassLoadEvent (org.hotswap.agent.annotation.OnClassLoadEvent)16 CtClass (org.hotswap.agent.javassist.CtClass)8 CtMethod (org.hotswap.agent.javassist.CtMethod)6 NotFoundException (org.hotswap.agent.javassist.NotFoundException)5 WeldPlugin (org.hotswap.agent.plugin.weld.WeldPlugin)4 CtField (org.hotswap.agent.javassist.CtField)3 CannotCompileException (org.hotswap.agent.javassist.CannotCompileException)2 ExprEditor (org.hotswap.agent.javassist.expr.ExprEditor)2 IOException (java.io.IOException)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1 ArrayList (java.util.ArrayList)1 Command (org.hotswap.agent.command.Command)1 PluginManager (org.hotswap.agent.config.PluginManager)1 CtBehavior (org.hotswap.agent.javassist.CtBehavior)1 MethodInfo (org.hotswap.agent.javassist.bytecode.MethodInfo)1 FieldAccess (org.hotswap.agent.javassist.expr.FieldAccess)1 MethodCall (org.hotswap.agent.javassist.expr.MethodCall)1 DeltaSpikePlugin (org.hotswap.agent.plugin.deltaspike.DeltaSpikePlugin)1