All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.datanucleus.enhancer.AbstractImplementationCreator Maven / Gradle / Ivy

/**********************************************************************
Copyright (c) 2005 Erik Bengtson 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:
2007 Andy Jefferson - added superclass, cater for abstract classes
    ...
**********************************************************************/
package org.datanucleus.enhancer;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import javax.jdo.JDOException;
import javax.jdo.JDOFatalException;
import javax.jdo.JDOUserException;
import javax.jdo.spi.PersistenceCapable;

import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.ImplementationCreator;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.metadata.ClassMetaData;
import org.datanucleus.metadata.InterfaceMetaData;
import org.datanucleus.metadata.MetaDataManager;
import org.datanucleus.util.ClassUtils;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.NucleusLogger;

/**
 * Abstract representation of an implementation creator. 
 * Creates implementations of interfaces or abstract classes.
 */
public abstract class AbstractImplementationCreator implements ImplementationCreator
{
    protected static final Localiser LOCALISER = Localiser.getInstance(
        "org.datanucleus.enhancer.Localisation", ClassEnhancer.class.getClassLoader());

    /** MetaData manager to use. */
    protected final MetaDataManager metaDataMgr;

    /** ClassLoader for newly defined classes **/
    protected final EnhancerClassLoader loader;

    /**
     * Constructor.
     * @param mmgr MetaData manager
     */
    public AbstractImplementationCreator(MetaDataManager mmgr)
    {
        metaDataMgr = mmgr;
        loader = new EnhancerClassLoader();
    }

    /**
     * Method to generate an instance of an interface, abstract class, or concrete PC class.
     * @param cls The class of the interface, abstract class, or concrete class defined in MetaData
     * @param clr ClassLoader resolver
     * @return The instance of this type
     */
    public Object newInstance(Class cls, ClassLoaderResolver clr)
    {
        try
        {
            if (PersistenceCapable.class.isAssignableFrom(cls))
            {
                if (Modifier.isAbstract(cls.getModifiers()))
                {
                    // Abstract class, so we need an implementation
                    ClassMetaData cmd = (ClassMetaData)metaDataMgr.getMetaDataForClass(cls, clr);
                    if (cmd == null)
                    {
                        throw new JDOFatalException("Could not find metadata for class " + cls.getName());
                    }

                    Object obj = newInstance(cmd, clr);
                    if (obj == null)
                    {
                        throw new JDOFatalException(LOCALISER.msg("ImplementationCreator.InstanceCreateFailed", cls.getName()));
                    }
                    if (!metaDataMgr.hasMetaDataForClass(obj.getClass().getName()))
                    {
                        // No metadata yet present for the implementation so register it
                        metaDataMgr.registerImplementationOfAbstractClass(cmd, obj.getClass(), clr);
                    }
                    return obj;
                }
                else
                {
                    // Concrete class that is PC so just create an instance using its no args constructor
                    return cls.newInstance();
                }
            }
            else
            {
                // Interface, so we need an implemenation
                InterfaceMetaData imd = metaDataMgr.getMetaDataForInterface(cls, clr);
                if (imd == null)
                {
                    throw new JDOFatalException("Could not find metadata for class/interface "+cls.getName());
                }

                Object obj = newInstance(imd, clr);
                if (obj == null)
                {
                    throw new JDOFatalException(LOCALISER.msg("ImplementationCreator.InstanceCreateFailed", cls.getName()));
                }
                if (!metaDataMgr.hasMetaDataForClass(obj.getClass().getName()))
                {
                    // No metadata yet present for the implementation so register it
                    metaDataMgr.registerPersistentInterface(imd, obj.getClass(), clr);
                }
                return obj;
            }
        }
        catch (ClassNotFoundException e)
        {
            throw new JDOUserException(e.toString(),e);
        }
        catch (InstantiationException e)
        {
            throw new JDOUserException(e.toString(),e);
        }
        catch (IllegalAccessException e)
        {
            throw new JDOUserException(e.toString(),e);
        }
    }

    /**
     * Constructs an implementation for an interface and instantiates it.
     * @param imd The MetaData for the interface
     * @param clr The ClassLoader
     * @return The instance implementing the interface
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */    
    protected PersistenceCapable newInstance(InterfaceMetaData imd, ClassLoaderResolver clr) 
    throws ClassNotFoundException, InstantiationException, IllegalAccessException
    {
        // Check that all methods of the interface are declared as persistent properties
        Class cls = clr.classForName(imd.getFullClassName());
        Method[] methods = cls.getDeclaredMethods();
        for (int i=0;i> AbstractImplCreator implClassName=" + implClassName + 
                " gen=" + gen + " bytes=" + (gen.getBytes() != null ? new String(gen.getBytes()) : null));
            gen.enhance(clr);
            this.loader.defineClass(implFullClassName, gen.getBytes(), clr);
        }

        // Create an instance of the class using default constructor
        Object instance = this.loader.loadClass(implFullClassName).newInstance();
        if (instance instanceof PersistenceCapable)
        {
            return (PersistenceCapable) instance;
        }
        else
        {
            // Generated instance is not PersistenceCapable for some reason so generate a suitable exception
            // TODO Correct this message for abstract classes
            Class interfaces[] = instance.getClass().getInterfaces();
            StringBuilder implementedInterfacesMsg = new StringBuilder("[");
            String classLoaderPCMsg = "";
            for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy