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; } }