Package org.objectweb.speedo.generation.enhancer.common

Source Code of org.objectweb.speedo.generation.enhancer.common.MergedClassModifier

/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2005 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*
*
* Contact: speedo@objectweb.org
*
* Authors: S.Chassande-Barrioz.
*
*/
package org.objectweb.speedo.generation.enhancer.common;

import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.CodeAdapter;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

import java.util.ArrayList;
import java.util.List;

/**
* ASM visitor cleaning a visited class to merge to another:
* <ul>
* <li>keep only one "class$" method</li>
* <li>rename a static section in order to agregate all at the end</li>
* <li>do not merge abstract method</li>
* <li>do not merge constructor</li>
* <li>do not merge this method</li>
* </ul>
*
* @author S.Chassande-Barrioz
*/
public class MergedClassModifier extends LoggedClassAdapter {
    private String classToWrite;
    private String oldClass;
    boolean hasDotClassMethod;
    List methodNames;

    /**
     * Builds the visitor
     *
     * @param classtowrite
     *            is the final name of the class to write
     * @param oldclassName is the old name of the class.      
     */
    public MergedClassModifier(final ClassVisitor classVisitor,
            final String classtowrite,
            final String oldclassName,
            final Logger logger,
            final Personality p) {
        super(classVisitor, p, logger);
        this.classToWrite = getJVMClassName(classtowrite);
        this.oldClass = getJVMClassName(oldclassName);
        this.methodNames = new ArrayList();
    }

    // IMPLEMENTATION OF THE ClassVisitor INTERFACE //
    // ---------------------------------------------//

    public CodeVisitor visitMethod(final int access, final String name,
            final String desc, final String[] exceptions, final Attribute attrs) {
        String mn = name;
        if ("class$".equals(name)) {
            // keep only one "class$" method
            if (hasDotClassMethod) {
                // remove useless .class static method
                return null;
            } else {
                // First .class static method
                hasDotClassMethod = true;
            }
        } else if ("<clinit>".equals(name)) {
            // rename a static section in order to agregate all at the end
            mn = "clinit$" + methodNames.size();
            methodNames.add(mn);
            if (debug) {
                logger
                        .log(BasicLevel.DEBUG, "rename a static section to "
                                + mn);
            }
        } else if ((access & Constants.ACC_ABSTRACT) != 0) {
            // do not merge abstract method
            return null;
        } else if (name.equals("<init>")) {
            // do not merge constructor
            return null;
        } else if (name.equals("this")) {
            // do not merge this method
            return null;
        }
        //Modifies instructions that reference the old class.
        CodeVisitor mv = cv.visitMethod(access, mn, desc, exceptions, attrs);
        if (mv != null) {
            mv = new CodeRenamer(mv, oldClass, classToWrite);
        }
        return mv;
    }

    public void visitEnd() {
        // Merge the static initializer
        if (methodNames.size() > 0) {
            CodeVisitor mv = this.cv.visitMethod(Constants.ACC_STATIC,
                    "<clinit>", "()V", null, null);
            for (int i = 0; i < methodNames.size(); i++) {
                String methodName = (String) methodNames.get(i);
                mv.visitMethodInsn(Constants.INVOKESTATIC, classToWrite,
                        methodName, "()V");
            }
            mv.visitInsn(Constants.RETURN);
        }
        super.visitEnd();
    }

}
TOP

Related Classes of org.objectweb.speedo.generation.enhancer.common.MergedClassModifier

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.