Package org.objectweb.speedo.generation.mivisitor

Source Code of org.objectweb.speedo.generation.mivisitor.ClassInfoAnalyzer$ClassFieldFinder

/**
* Copyright (C) 2001-2004 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.mivisitor;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.CodeVisitor;
import org.objectweb.asm.Constants;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Attribute;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.speedo.metadata.SpeedoField;
import org.objectweb.speedo.api.SpeedoRuntimeException;
import org.objectweb.speedo.generation.api.SpeedoCompilerParameter;
import org.objectweb.speedo.generation.enhancer.common.AbstractEnhancerComponent;
import org.objectweb.speedo.generation.enhancer.common.LoggedClassVisitor;
import org.objectweb.speedo.generation.enhancer.common.Util;
import org.objectweb.util.monolog.api.Logger;
import org.objectweb.util.monolog.api.BasicLevel;

import java.io.ObjectStreamClass;
import java.util.Iterator;
import java.util.Map;
import java.util.Collection;

/**
* Analyzes a class and updates the Speedo meta information accordingly.
*
* Adapted from storeClassInfo, verify and getField methods in EnhancerTool.
*/
public class ClassInfoAnalyzer extends LoggedClassVisitor implements ClassVisitor {

    /**
     * The access enhancer, used to load the super class(es) of the class, if
     * necessary.
     */
    final AbstractEnhancerComponent enhancer;

    /**
     * The Speedo meta information for the visited class.
     */
    final SpeedoClass moClass;

    /**
     * A collection of SpeedoXMLDescriptor describing known persistent classes
     */
    private final Collection xmlDescriptors;

    /**
     * Creates a new {@link ClassInfoAnalyzer}.
     *
     * @param enhancer the access enhancer, used to load the super class(es) of
     * the class, if necessary.
     * @param sc the Speedo meta information for the visited class.
     */
    public ClassInfoAnalyzer(final AbstractEnhancerComponent enhancer,
                             final SpeedoClass sc,
                             final Collection xmlDescriptors,
                             Logger logger) {
        super(logger);
        this.enhancer = enhancer;
        this.moClass = sc;
        this.xmlDescriptors = xmlDescriptors;
    }

    protected void manageInheritance(String superName) {
        // Verifies inheritance
        String superClass = moClass.getSuperClassName();
        if (superClass != null && !superClass.equals(superName.replace('/', '.'))) {
            throw new SpeedoRuntimeException("Class " + moClass.getFQName() + " has actually " +
                    superName + " as super class, whereas the .jdo file spcifies '"
                    + moClass.getSuperClassName() + "'");
        }
    }
    protected void managedInterfaces(String[] interfaces) {
        // Gets implemented interfaces
        for (int i = 0; i < interfaces.length; i++) {
            if (interfaces[i].equals("javax/jdo/InstanceCallbacks"))
                moClass.isInstanceCallbacks = true;
            if (interfaces[i].equals("java/io/Serializable"))
                moClass.isSerializable = true;
        }
    }
   
    // IMPLEMENTATION OF THE ClassVisitor INTERFACE //
    // ---------------------------------------------//

    public void visit(final int version, final int access,
                      final String name,
                      final String superName,
                      final String[] interfaces,
                      final String sourceFile) {
        // Stores class's signature
        moClass.isAbstract = (access & Constants.ACC_ABSTRACT) != 0;
        manageInheritance(superName);
        managedInterfaces(interfaces);

        // Looks for fields defined in the speedoClass in the Java class and
        // assigns the corresponding modifier if missing
        ClassFieldFinder finder = new ClassFieldFinder();
        if (debug) {
            logger.log(BasicLevel.DEBUG, "field names: "
                    + moClass.fields.keySet());
            logger.log(BasicLevel.DEBUG, "fields ["
                    + moClass.fields.values().size() + "]: "
                    + moClass.fields.values());
        }
        for(Iterator it = moClass.fields.values().iterator(); it.hasNext();) {
            SpeedoField current = (SpeedoField) it.next();
            if (debug) {
                logger.log(BasicLevel.DEBUG, "treat  field " + current.name);
            }
            if (!finder.fillInfo(current)) {
                throw new SpeedoRuntimeException(
                        "Persistent Field " + current.name +
                        " not defined in class " + name);
            }
            if (current.persistenceStatus == SpeedoField.UNKNOWN) {
                current.persistenceStatus =
                        Util.isPersistentType(current.type, xmlDescriptors)
                            ? SpeedoField.PERSISTENT
                            : SpeedoField.NONE;
            }
        }
        // Stores the serial version uid for serializable classes
        if (moClass.isSerializable) {
            try {
                ObjectStreamClass oserial = ObjectStreamClass.lookup(
                        Class.forName(name.replace('/', '.')));
            } catch (Exception e) {
                logger.log(BasicLevel.WARN,
                        "Impossible to find the VersionUID of the class", e);
            }
        }
    }

    public void visitInnerClass(final String name,
                                final String outerName,
                                final String innerName,
                                final int access) {
        // does nothing
    }

    public void visitField(final int access,
                           final String name,
                           final String desc,
                           final Object value,
                           final Attribute attrs) {
        // Adds in the object model fields whose type is known as
        // Persistence Capable
        if ((access & Constants.ACC_STATIC) == 0
              && (access & Constants.ACC_FINAL) == 0
              && (access & Constants.ACC_SYNTHETIC) == 0) {
          SpeedoField jdoField = (SpeedoField) moClass.fields.get(name);
          if (jdoField == null
                  && Util.isAutomaticPersistentType(desc, xmlDescriptors)) {
        jdoField = new SpeedoField();
        jdoField.persistenceStatus = SpeedoField.PERSISTENT;
        jdoField.name = name;
        jdoField.visibility = access;
        jdoField.type = desc;
        moClass.add(jdoField);
      }
        }
    }

    public CodeVisitor visitMethod(final int access,
                                   final String name,
                                   final String desc,
                                   final String[] exceptions,
                                   final Attribute attrs) {
        if ("<init>".equals(name) && "()V".equals(desc)) {
      moClass.noArgConstructorStatus = ((access & Constants.ACC_PUBLIC) == 0
        ? SpeedoClass.NON_PUBLIC_NO_ARG_CONSTRUCTOR
        : SpeedoClass.PUBLIC_NO_ARG_CONSTRUCTOR);
      if (logger.isLoggable(BasicLevel.DEBUG)) {
        logger.log(BasicLevel.DEBUG, moClass.getFQName()
          + ".noArgConstructorStatus=" + moClass.noArgConstructorStatus);
      }
    }
        return null;
    }

    public void visitAttribute(Attribute attribute) {
        // does nothing
    }

    public void visitEnd() {
        // Removes from the object model all fields that are not defined as
        // persistent
        for (Iterator it = moClass.fields.entrySet().iterator();it.hasNext();) {
            Map.Entry entry = (Map.Entry) it.next();
            SpeedoField field = (SpeedoField) entry.getValue();
            if (field.persistenceStatus != SpeedoField.PERSISTENT) {
                it.remove();
            }
        }
    }

    /**
     * Looks for a field in a class, and in its (persistent) super classes.
     */
    class ClassFieldFinder implements ClassVisitor {

        /**
         * Information about this field, if found.
         */
        private SpeedoField result;
      boolean find = false;

        public boolean fillInfo(SpeedoField sf) {
          this.result = sf;
          String className = sf.moClass.getFQName();
            SpeedoCompilerParameter scp = enhancer.getSpeedoCompilerParameter();
            try {
              find = false;
                while (true) {
                    // lookup in the class if the field exists
                    ClassReader cr = enhancer.loadJavaClass(enhancer.isSrcJar,
                                className, scp.output, false);
                    cr.accept(this, true);
                    if (find) {
                        return true;
                    }

                    // lookup in the super class, if applicable
                    className = moClass.getSuperClassName();
                    if (className == null) {
                        // The current class has not a superclasses and the
                        // field has not been found
                        return false;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }

        public void visit(final int version,
                      final int access,
                          final String name,
                          final String superName,
                          final String[] interfaces,
                          final String sourceFile) {
            // does nothing
        }

        public void visitInnerClass(final String name,
                                    final String outerName,
                                    final String innerName,
                                    final int access) {
            // does nothing
        }

        public void visitField(final int access,
                               final String name,
                               final String desc,
                               final Object value,
                               final Attribute attrs) {
            if (name.equals(result.name)) {
                // we have found the field we are looking for
                result.visibility = access;
                result.type = desc;
              find = true;
            }
        }

        public CodeVisitor visitMethod(final int access,
                                       final String name,
                                       final String desc,
                                       final String[] exceptions,
                                       final Attribute attrs) {
            // this visitor does not need to visit the code of methods
            return null;
        }

        public void visitAttribute(Attribute attribute) {
            // does nothing
        }

        public void visitEnd() {
            // does nothing
        }
    }
}
TOP

Related Classes of org.objectweb.speedo.generation.mivisitor.ClassInfoAnalyzer$ClassFieldFinder

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.