org.coldswap.transformer.ClInitTransformer.java Source code

Java tutorial

Introduction

Here is the source code for org.coldswap.transformer.ClInitTransformer.java

Source

package org.coldswap.transformer;

import org.coldswap.util.ClassUtil;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.List;
import java.util.logging.Logger;

/**
 * (C) Copyright 2013 Faur Ioan-Aurel.
 * <p/>
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 * <p/>
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * <p/>
 * Contributors:
 * faur
 * <p/>
 * Created at:
 * 7:43 PM       3/19/13
 */

/**
 * Searches the class before is loaded to find the
 * static initializer method(<clinit>). If it is not founded
 * insert a default one.
 */
public class ClInitTransformer implements ClassFileTransformer {
    private final static Logger logger = Logger.getLogger(ClInitTransformer.class.getName());

    static {
        logger.setLevel(ClassUtil.logLevel);
    }

    @SuppressWarnings("unchecked")
    @Override
    public byte[] transform(ClassLoader classLoader, String s, Class<?> aClass, ProtectionDomain protectionDomain,
            byte[] bytes) throws IllegalClassFormatException {
        if (s != null && !"".equals(s)) {
            for (String pack : ClassUtil.skipTransforming) {
                if (s.startsWith(pack)) {
                    return bytes;
                }
            }

            ClassNode cn = new ClassNode(Opcodes.ASM5);
            ClassReader cr = new ClassReader(bytes);
            ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
            // create adapter for method insertion.
            cr.accept(cn, 0);
            // insert <clinit>V if it is not inserted
            List methods = cn.methods;
            boolean clInitFound = false;
            for (MethodNode methodNode : (List<MethodNode>) methods) {
                if ("<clinit>".equals(methodNode.name)) {
                    clInitFound = true;
                }
            }

            if (!clInitFound) {
                MethodNode mn = new MethodNode(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
                InsnList insnList = mn.instructions;
                insnList.add(new LabelNode());
                insnList.add(new InsnNode(Opcodes.RETURN));
                cn.methods.add(mn);
            }

            cn.accept(cw);
            byte[] toRet = cw.toByteArray();
            if (toRet != null) {
                logger.info("Successful transformation!");
                return toRet;
            } else {
                logger.severe("Could not transform class");
                return bytes;
            }
        }
        return bytes;
    }
}