Package org.jpox.enhancer.bcel.metadata

Source Code of org.jpox.enhancer.bcel.metadata.BCELClassMetaData

/**********************************************************************
Copyright (c) 2004 Kikuchi Kousuke 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:
2004 Andy Jefferson - added JPOX MetaData checks
2004 Andy Jefferson - changed to extend ClassMetaData
2004 Andy Jefferson - removed fix() methods, using ClassMetaData.populate()
2004 Andy Jefferson - fixed findField() to allow for superclasses
2005 Andy Jefferson - renamed
    ...
**********************************************************************/
package org.jpox.enhancer.bcel.metadata;

import javax.jdo.JDOFatalException;

import org.apache.bcel.Repository;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.generic.ClassGen;
import org.jpox.JDOClassLoaderResolver;
import org.jpox.enhancer.ClassEnhancer;
import org.jpox.enhancer.bcel.JPOXRepository;
import org.jpox.metadata.AbstractMemberMetaData;
import org.jpox.metadata.ClassMetaData;
import org.jpox.metadata.FieldMetaData;
import org.jpox.metadata.InterfaceMetaData;
import org.jpox.metadata.PackageMetaData;
import org.jpox.util.JPOXLogger;
import org.jpox.util.Localiser;

/**
* Extension of the standard ClassMetaData adding on attributes for enhancement
* of the class.
*
* @version $Revision: 1.11 $
*/
public class BCELClassMetaData extends ClassMetaData
{
    protected static final Localiser LOCALISER_ENH = Localiser.getInstance("org.jpox.enhancer.Localisation",ClassEnhancer.class.getClassLoader());

    /** BCEL class gen. */
    protected final ClassGen classGen;

    /** Original BCEL java class. */
    protected final JavaClass enhanceClass;

    /**
     * Constructor for creating the ClassMetaData for an implementation of a "persistent-interface".
     * @param imd MetaData for the "persistent-interface"
     * @param implClassName Name of the implementation class
     * @param enhanceClass The enhanced class
     */
    public BCELClassMetaData(InterfaceMetaData imd, String implClassName, final JavaClass enhanceClass)
    {
        super(imd, implClassName, false); // Dont copy the fields because we need the classGen set first

        this.enhanceClass = enhanceClass;

        // Make sure we have a JPOXRepository
        if (Repository.getRepository() == null || !(Repository.getRepository() instanceof JPOXRepository))
        {
            Repository.setRepository(new JPOXRepository(new JDOClassLoaderResolver()));
        }
        Repository.addClass(enhanceClass);
        classGen = new ClassGen(this.enhanceClass);

        // Copy fields after we have the classGen set
        copyMembersFromInterface(imd);
    }

    /**
     * Constructor.
     */
    public BCELClassMetaData(final PackageMetaData parent,
                          final String name,
                          final String identityType,
                          final String objectidClass,
                          final String requiresExtent,
                          final String detachable,
                          final String embeddedOnly,
                          final String modifier,
                          final String persistenceCapableSuperclass,
                          final String catalog,
                          final String schema,
                          final String table,
                          final String entityName)
    {
        super(parent, name, identityType, objectidClass, requiresExtent, detachable, embeddedOnly, modifier, persistenceCapableSuperclass,
            catalog, schema, table, entityName);

        // Make sure we have a JPOXRepository
        if (Repository.getRepository() == null || !(Repository.getRepository() instanceof JPOXRepository))
        {
            Repository.setRepository(new JPOXRepository(new JDOClassLoaderResolver()));
        }
        // Store the class and generator for enhancement later
        try
        {
            enhanceClass = Repository.lookupClass(fullName);
        }
        catch (Throwable ex)
        {
            //catch Throwable, so it is compatible with latest BCEL changes in methods signature.
            //It nows raises ClassNotFoundException. In order to be able to compible this code
            //with bcel-5.1 or bcel-5.1+, we catch as throwable
            String msg = LOCALISER_ENH.msg("Enhancer.ClassNotFound", fullName, ex);
            JPOXLogger.ENHANCER.error(msg);
            throw new JDOFatalException(msg, ex);
        }
        if (enhanceClass == null)
        {
            String msg = LOCALISER_ENH.msg("Enhancer.ClassNotFound", fullName, "");
            JPOXLogger.ENHANCER.error(msg);
            throw new JDOFatalException(msg);
        }

        classGen = new ClassGen(this.enhanceClass);
    }

    /**
     * Convenience method to copy the fields from an existing interface
     * @param imd The class/interface that we copy from
     */
    protected void copyMembersFromInterface(InterfaceMetaData imd)
    {
        for (int i=0; i<imd.getNoOfInheritedManagedMembers()+imd.getNoOfManagedMembers(); i++)
        {
            FieldMetaData fmd = new BCELFieldMetaData(this, imd.getMetaDataForManagedMemberAtAbsolutePosition(i));
            addMember(fmd);
        }
    }

    /**
     * Utility to add a defaulted FieldMetaData to the class. Override the
     * method in ClassMetaData because we want to add JDOConfigField type.
     * This is called when using populate() and the class has a field that
     * isn't in the MetaData.
     * @param name name of field
     */
    protected AbstractMemberMetaData newDefaultedProperty(String name)
    {
        return new BCELFieldMetaData(this, name);
    }

    /**
     * Return ClassGen instance of bcel
     * @return ClassGen instance of bcel
     */
    public ClassGen getClassGen()
    {
        return classGen;
    }

    /**
     * Return original JavaClass instance of bcel
     * @return original JavaClass instance of bcel
     */
    public JavaClass getEnhanceClass()
    {
        return enhanceClass;
    }

    /**
     * Find the specified field.
     * Caters for the field being in this class, or in its superclass(es).
     * @param f The field
     * @return The metadata for the field
     */
    public AbstractMemberMetaData findField(Field f)
    {
        if (f == null)
        {
            throw new NullPointerException("field is null");
        }

        String name = f.getName();
        for (int i = 0; i < members.size(); i++)
        {
            AbstractMemberMetaData fieldConfig = getMetaDataForMemberAtRelativePosition(i);
            if (fieldConfig.fieldBelongsToClass())
            {
                if( fieldConfig.getName().equals(name) )
                {
                    // Dont return our field if we are overriding one for a superclass
                    return fieldConfig;
                }
            }
        }

        // If superclass exists, try there
        if (pcSuperclassMetaData != null)
        {
            return ((BCELClassMetaData)pcSuperclassMetaData).findField(f);
        }

        return null;
    }

    /**
     * Find the specified property (getter/setter) for a java field
     * Caters for the property being in this class, or in its superclass(es).
     * @param f The field
     * @return The metadata for the property
     */
    public AbstractMemberMetaData findProperty(Field f)
    {
        if (f == null)
        {
            throw new NullPointerException("field is null");
        }

        String name = f.getName();
        for (int i = 0; i < members.size(); i++)
        {
            AbstractMemberMetaData fieldConfig = getMetaDataForMemberAtRelativePosition(i);
            if (fieldConfig.fieldBelongsToClass())
            {
                if( fieldConfig.isProperty() && fieldConfig.getName().equals(name) )
                {
                    // Dont return our field if we are overriding one for a superclass
                    return fieldConfig;
                }
            }
        }

        // If superclass exists, try there
        if (pcSuperclassMetaData != null)
        {
            return ((BCELClassMetaData)pcSuperclassMetaData).findField(f);
        }

        return null;
    }

}
TOP

Related Classes of org.jpox.enhancer.bcel.metadata.BCELClassMetaData

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.