org.datanucleus.enhancer.AbstractImplementationCreator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datanucleus-enhancer Show documentation
Show all versions of datanucleus-enhancer Show documentation
DataNucleus Enhancer is a Java byte-code enhancer for use with DataNucleus.
The newest version!
/**********************************************************************
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