Package org.objectweb.speedo.generation.enhancer.pc.jdo

Source Code of org.objectweb.speedo.generation.enhancer.pc.jdo.JDOImplRegistrationAdder

/**
* 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
*/
package org.objectweb.speedo.generation.enhancer.pc.jdo;

import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.asm.Label;
import org.objectweb.speedo.generation.enhancer.common.LoggedClassAdapter;
import org.objectweb.speedo.generation.lib.NamingRules;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.tools.StringReplace;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

/**
* Add the registration to the JDOImplHelper in a static code area
*
* The added code use the class$(String)Class method and the field
* class$classname which can exist or not. Therefore they are added if they do
* not already exist.
*
* @author S.Chassande-Barrioz
*/
public class JDOImplRegistrationAdder extends LoggedClassAdapter {
    private final static String FIELD_PREFIX = "class$";
    private final static String CLASS_METH = "class$";
  /**
   * Class name of the current visited class (with slash separator)
   */
  private final String classToWrite;
  /**
   * indicates if the field already exists in the current class
   */
  boolean clinitfound = false;
  /**
   * indicates if a static area class$classname already exists in the
   * current class.
   */
  boolean classFieldfound = false;
  /**
   * indicates if the class$ method already exists in the current class
   */
  boolean classMethodfound = false;
  /**
   * is the name of the static field referencing the java.lang.Class of
   * the current class.
   */
  private final String fieldName;
    private boolean generationAllowed = false;
 
  public JDOImplRegistrationAdder(ClassVisitor classVisitor,
            String className,
            Logger logger) {
    super(classVisitor, Personality.JDO, logger);
        this.classToWrite = getJVMClassName(className);
        this.fieldName = FIELD_PREFIX + classToWrite.replace('/', '$');
  }

  public boolean isGenerationAllowed() {
        return generationAllowed;
    }

    public void setGenerationAllowed(boolean v) {
        this.generationAllowed = v;
    }

    public void visit(final int version, final int access,
            final String name,
            final String superName,
            final String[] interfaces,
            final String sourceFile) {
    super.visit(version, access, name, superName, interfaces, sourceFile);
  }

  public void visitField(int i, String s, String s1, Object o, Attribute attribute) {
    super.visitField(i, s, s1, o, attribute);
    classFieldfound |= s.equals(fieldName);
  }

  public CodeVisitor visitMethod(final int access,
                   final String name,
                   final String desc,
                   final String[] exceptions,
                   final Attribute attrs) {
    CodeVisitor c = cv.visitMethod(access, name, desc, exceptions, attrs);
    if (name.equals("<clinit>")) {
      clinitfound = true;
      addClassRegistrationCode(c);
    } else if (name.equals(CLASS_METH)) {
      classMethodfound = true;
    }
    return c;
  }

  public void visitEnd() {
        if (generationAllowed) {
        if (!clinitfound) {
          logger.log(BasicLevel.DEBUG, "Adding static area in " + classToWrite);
          CodeVisitor c = cv.visitMethod(Constants.ACC_STATIC,
            "<clinit>", "()V", null, null);
          addClassRegistrationCode(c);
          c.visitInsn(RETURN);
          c.visitMaxs(0, 0);
                clinitfound = true;
        }
   
        if (!classMethodfound) {
                classMethodfound = true;
          logger.log(BasicLevel.DEBUG, "Adding static method class$(String)Class in " + classToWrite);
          CodeVisitor c = cv.visitMethod(ACC_STATIC + ACC_SYNTHETIC, CLASS_METH,
            "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
          //try {
                final Label l0 = new Label();
          c.visitLabel(l0);
          //return Class.forName(str)
                c.visitVarInsn(ALOAD, 0);
          c.visitMethodInsn(INVOKESTATIC, "java/lang/Class", "forName",
            "(Ljava/lang/String;)Ljava/lang/Class;");
          final Label l1 = new Label();
          c.visitLabel(l1);
          c.visitInsn(ARETURN);
                final Label l2 = new Label();
          c.visitLabel(l2);
          c.visitVarInsn(ASTORE, 1);
          c.visitTypeInsn(NEW, "java/lang/NoClassDefFoundError");
          c.visitInsn(DUP);
          c.visitVarInsn(ALOAD, 1);
          c.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ClassNotFoundException",
            "getMessage", "()Ljava/lang/String;");
          c.visitMethodInsn(INVOKESPECIAL, "java/lang/NoClassDefFoundError",
            "<init>", "(Ljava/lang/String;)V");
          c.visitInsn(ATHROW);
          c.visitTryCatchBlock(l0, l1, l2, "java/lang/ClassNotFoundException");
          c.visitMaxs(0, 0);
        }
        if (!classFieldfound) {
                classFieldfound = true;
          logger.log(BasicLevel.DEBUG, "Adding static field '"
                        + fieldName + " in " + classToWrite);
          cv.visitField(ACC_STATIC + ACC_SYNTHETIC, fieldName,
            "Ljava/lang/Class;", null, null);
        }
        }
    super.visitEnd();
  }
 
  /**
   * Add registration code of the class into the JDOImplHelper
   * @param c
   */
  private void addClassRegistrationCode(CodeVisitor c) {     
    //Class thepc
      c.visitFieldInsn(Constants.GETSTATIC,
      classToWrite,
      fieldName,
      "Ljava/lang/Class;");

    final Label l1 = new Label();
    c.visitJumpInsn(Constants.IFNONNULL, l1);
    c.visitLdcInsn(StringReplace.replaceChar('/', '.', classToWrite));
    c.visitMethodInsn(Constants.INVOKESTATIC, classToWrite, CLASS_METH,
            "(Ljava/lang/String;)Ljava/lang/Class;");
    c.visitInsn(Constants.DUP);
    c.visitFieldInsn(Constants.PUTSTATIC,
                classToWrite,
      fieldName,
      "Ljava/lang/Class;");
    final Label l2 = new Label();
    c.visitJumpInsn(Constants.GOTO, l2);
    c.visitLabel(l1);
    c.visitFieldInsn(Constants.GETSTATIC,
                classToWrite,
      fieldName,
      "Ljava/lang/Class;");
    c.visitLabel(l2);
        final String homeClassName = NamingRules.homeName(classToWrite);
    //String[] field names
    c.visitFieldInsn(GETSTATIC, homeClassName, "FIELD_NAMES", "[Ljava/lang/String;");
    //Class[] fieldTypes
    c.visitFieldInsn(GETSTATIC, homeClassName, "FIELD_TYPES", "[Ljava/lang/Class;");
    //byte[] fieldFlags
    c.visitFieldInsn(GETSTATIC, homeClassName, "FIELD_FLAGS", "[B");
    //Class superClass
    c.visitFieldInsn(GETSTATIC, homeClassName, "SUPER_CLASS", "Ljava/lang/Class;");
    //PersistentCapable
    c.visitInsn(ACONST_NULL);
    c.visitMethodInsn(Constants.INVOKESTATIC,
      "javax/jdo/spi/JDOImplHelper",
      "registerClass",
      "(Ljava/lang/Class;[Ljava/lang/String;[Ljava/lang/Class;[BLjava/lang/Class;Ljavax/jdo/spi/PersistenceCapable;)V");
  }
}
TOP

Related Classes of org.objectweb.speedo.generation.enhancer.pc.jdo.JDOImplRegistrationAdder

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.