Package org.jpox.enhancer.asm

Source Code of org.jpox.enhancer.asm.JdoClassChecker

/**********************************************************************
Copyright (c) 2007 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
    ...
**********************************************************************/
package org.jpox.enhancer.asm;

import java.util.HashSet;
import java.util.Iterator;

import org.jpox.enhancer.ClassEnhancer;
import org.jpox.enhancer.ClassField;
import org.jpox.enhancer.ClassMethod;
import org.jpox.metadata.ClassPersistenceModifier;
import org.jpox.util.JPOXLogger;
import org.jpox.util.Localiser;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;

/**
* Visitor used to check the enhancement state of a class.
* Checks the methods/fields present against what is required for JDO enhancement.
* @version $Revision: 1.7 $
*/
public class JdoClassChecker implements ClassVisitor
{
    /** Message resource */
    protected static Localiser LOCALISER=Localiser.getInstance("org.jpox.enhancer.Localisation",
        ClassEnhancer.class.getClassLoader());

    /** Enhancer for the class. */
    protected ASMClassEnhancer enhancer;

    /** Set of fields required to be present for JDO. */
    protected HashSet fieldsRequired = new HashSet();

    /** Set of methods required to be present for JDO. */
    protected HashSet methodsRequired = new HashSet();

    /** Flag for whether the class is enhanced. Set in the visit process. */
    protected boolean enhanced = false;

    /** Whether to log any errors at error level. */
    protected boolean logErrors = true;

    /**
     * Constructor.
     * @param enhancer The class enhancer
     * @param logErrors Whether to log any errors at error level
     */
    public JdoClassChecker(ASMClassEnhancer enhancer, boolean logErrors)
    {
        this.enhancer = enhancer;
        this.logErrors = logErrors;
        if (enhancer.getClassMetaData().getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE)
        {
            fieldsRequired.addAll(enhancer.getFieldsList());
            methodsRequired.addAll(enhancer.getMethodsList());
        }
    }

    /**
     * Accessor for whether the class is considered enhanced.
     * Should only be run after passing this class to the reader as a visitor.
     * @return Whether the class is enhanced.
     */
    public boolean isEnhanced()
    {
        return enhanced;
    }

    /**
     * Convenience method to report an error in the enhancement of this class.
     * @param msg The message
     */
    protected void reportError(String msg)
    {
        if (logErrors)
        {
            JPOXLogger.ENHANCER.error(msg);
        }
        else
        {
            JPOXLogger.ENHANCER.info(msg);
        }
        enhanced = false;
    }

    /**
     * Method to visit the header of the class
     * @param version Version of the class file
     * @param access Access type
     * @param name name of the class
     * @param signature signature of the class
     * @param supername superclass name
     * @param interfaces interface(s)
     */
    public void visit(int version, int access, String name, String signature, String supername, String[] interfaces)
    {
        enhanced = true; // Default to true unless we find a problem
        if (enhancer.getClassMetaData().getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE)
        {
            if (interfaces == null)
            {
                enhanced = false;
                return;
            }

            if (!hasInterface(interfaces, ASMUtils.ACN_PersistenceCapable))
            {
                reportError(LOCALISER.msg("Enhancer.Check.InterfaceMissing", enhancer.className,
                    "javax.jdo.spi.PersistenceCapable"));
            }

            if (enhancer.getClassMetaData().isDetachable())
            {
                if (!hasInterface(interfaces, ASMUtils.ACN_Detachable))
                {
                    reportError(LOCALISER.msg("Enhancer.Check.InterfaceMissing", enhancer.className,
                        "javax.jdo.spi.Detachable"));
                }
            }
        }
    }

    /**
     * Convenience method to check if a particular interface is present in the list.
     * @param interfaces The list of interfaces implemented
     * @param intf The interface we are looking for
     * @return Whether it is present
     */
    protected boolean hasInterface(String[] interfaces, String intf)
    {
        if (interfaces == null || interfaces.length <= 0)
        {
            return false;
        }

        for (int i=0;i<interfaces.length;i++)
        {
            if (interfaces[i].equals(intf))
            {
                return true;
            }
        }
        return false;
    }

    /**
     * Method to visit a class annotations
     * @param desc descriptor of the annotation
     * @param visible Whether visible
     * @return The visitor
     */
    public AnnotationVisitor visitAnnotation(String desc, boolean visible)
    {
        return null;
    }

    /**
     * Method to visit a non-standard attribute
     * @param attr the attribute
     */
    public void visitAttribute(Attribute attr)
    {
    }

    /**
     * Visit the end of the class
     */
    public void visitEnd()
    {
        if (enhancer.getClassMetaData().getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE)
        {
            // Check for required PersistenceCapable fields/methods
            Iterator fieldsIter = fieldsRequired.iterator();
            while (fieldsIter.hasNext())
            {
                ClassField field = (ClassField)fieldsIter.next();
                reportError(LOCALISER.msg("Enhancer.Check.FieldMissing", enhancer.className, field.getName()));
            }

            Iterator methodsIter = methodsRequired.iterator();
            while (methodsIter.hasNext())
            {
                ClassMethod method = (ClassMethod)methodsIter.next();
                reportError(LOCALISER.msg("Enhancer.Check.MethodMissing", enhancer.className, method.getName()));
            }
        }
        else if (enhancer.getClassMetaData().getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_AWARE)
        {
            // TODO Fix this so we do a real check on whether the existing methods are enhanced ok
            enhanced = false;
        }
    }

    /**
     * Visit a field of the class.
     * @param access Access for the field
     * @param name name of the field
     * @param desc Descriptor of the field
     * @param signature signature of the field
     * @param value initial value
     * @return The visitor for the field
     */
    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
    {
        Iterator iter = fieldsRequired.iterator();
        while (iter.hasNext())
        {
            ClassField field = (ClassField)iter.next();
            if (field.getName().equals(name))
            {
                if (field.getAccess() != access)
                {
                    reportError(LOCALISER.msg("Enhancer.Check.FieldIncorrectAccess", enhancer.className, name));
                }
                else if (!desc.equals(Type.getDescriptor((Class)field.getType())))
                {
                    reportError(LOCALISER.msg("Enhancer.Check.FieldIncorrectType", enhancer.className, name));
                }
                else
                {
                    // Remove the field since it is present
                    iter.remove();
                    break;
                }
            }
        }
        return null;
    }

    /**
     * Visit an inner class of the class
     * @param name Internal name of the class
     * @param outerName name of the outer class
     * @param innerName name of the inner class
     * @param access access of the inner class
     */
    public void visitInnerClass(String name, String outerName, String innerName, int access)
    {
    }

    /**
     * Visit a method of the class
     * @param access Access for the field
     * @param name name of the field
     * @param desc Descriptor of the field
     * @param signature signature of the field
     * @param exceptions Exceptions thrown
     * @return visitor for the method
     */
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
    {
        Iterator iter = methodsRequired.iterator();
        while (iter.hasNext())
        {
            ASMClassMethod method = (ASMClassMethod)iter.next();
            if (method.getName().equals(name) && method.getDescriptor().equals(desc))
            {
                if (method.getAccess() != access)
                {
                    reportError(LOCALISER.msg("Enhancer.Check.MethodIncorrectAccess", enhancer.className, name));
                }
                else
                {
                    // Remove the method since it is present
                    iter.remove();
                    break;
                }
            }
        }

        // TODO Check enhancement of all fields to use jdoGetXXX, jdoSetXXX
        return null;
    }

    /**
     * Visit an outer class.
     * @param owner owner for the outer class
     * @param name name of the outer class
     * @param desc Descriptor of the outer class
     */
    public void visitOuterClass(String owner, String name, String desc)
    {
    }

    /**
     * Visit the source of the class
     * @param source name of source file
     * @param debug debug info
     */
    public void visitSource(String source, String debug)
    {
    }
}
TOP

Related Classes of org.jpox.enhancer.asm.JdoClassChecker

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.