HHH-3517 : default Tuplizer impls
git-svn-id: https://svn.jboss.org/repos/hibernate/core/branches/Branch_3_2@15289 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
c24cab0092
commit
969ba9a900
|
@ -38,6 +38,7 @@ import org.hibernate.InvalidMappingException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.MappingNotFoundException;
|
import org.hibernate.MappingNotFoundException;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.MySQLDialect;
|
import org.hibernate.dialect.MySQLDialect;
|
||||||
|
@ -133,6 +134,10 @@ public class Configuration implements Serializable {
|
||||||
protected Map sqlFunctions;
|
protected Map sqlFunctions;
|
||||||
protected Map namedQueries;
|
protected Map namedQueries;
|
||||||
protected Map namedSqlQueries;
|
protected Map namedSqlQueries;
|
||||||
|
|
||||||
|
private EntityTuplizerFactory entityTuplizerFactory;
|
||||||
|
// private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map<String, SqlResultSetMapping> result set name, result set description
|
* Map<String, SqlResultSetMapping> result set name, result set description
|
||||||
*/
|
*/
|
||||||
|
@ -158,6 +163,17 @@ public class Configuration implements Serializable {
|
||||||
|
|
||||||
protected final SettingsFactory settingsFactory;
|
protected final SettingsFactory settingsFactory;
|
||||||
|
|
||||||
|
private transient Mapping mapping = buildMapping();
|
||||||
|
|
||||||
|
protected Configuration(SettingsFactory settingsFactory) {
|
||||||
|
this.settingsFactory = settingsFactory;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Configuration() {
|
||||||
|
this( new SettingsFactory() );
|
||||||
|
}
|
||||||
|
|
||||||
protected void reset() {
|
protected void reset() {
|
||||||
classes = new HashMap();
|
classes = new HashMap();
|
||||||
imports = new HashMap();
|
imports = new HashMap();
|
||||||
|
@ -182,20 +198,17 @@ public class Configuration implements Serializable {
|
||||||
columnNameBindingPerTable = new HashMap();
|
columnNameBindingPerTable = new HashMap();
|
||||||
namingStrategy = DefaultNamingStrategy.INSTANCE;
|
namingStrategy = DefaultNamingStrategy.INSTANCE;
|
||||||
sqlFunctions = new HashMap();
|
sqlFunctions = new HashMap();
|
||||||
|
entityTuplizerFactory = new EntityTuplizerFactory();
|
||||||
|
// componentTuplizerFactory = new ComponentTuplizerFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
private transient Mapping mapping = buildMapping();
|
public EntityTuplizerFactory getEntityTuplizerFactory() {
|
||||||
|
return entityTuplizerFactory;
|
||||||
|
|
||||||
|
|
||||||
protected Configuration(SettingsFactory settingsFactory) {
|
|
||||||
this.settingsFactory = settingsFactory;
|
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Configuration() {
|
// public ComponentTuplizerFactory getComponentTuplizerFactory() {
|
||||||
this( new SettingsFactory() );
|
// return componentTuplizerFactory;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate the entity mappings
|
* Iterate the entity mappings
|
||||||
|
@ -2066,11 +2079,18 @@ public class Configuration implements Serializable {
|
||||||
public Settings buildSettings() throws HibernateException {
|
public Settings buildSettings() throws HibernateException {
|
||||||
Properties clone = ( Properties ) properties.clone();
|
Properties clone = ( Properties ) properties.clone();
|
||||||
PropertiesHelper.resolvePlaceHolders( clone );
|
PropertiesHelper.resolvePlaceHolders( clone );
|
||||||
return settingsFactory.buildSettings( clone );
|
return buildSettingsInternal( clone );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Settings buildSettings(Properties props) throws HibernateException {
|
public Settings buildSettings(Properties props) throws HibernateException {
|
||||||
return settingsFactory.buildSettings( props );
|
return buildSettingsInternal( props );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Settings buildSettingsInternal(Properties props) {
|
||||||
|
final Settings settings = settingsFactory.buildSettings( props );
|
||||||
|
settings.setEntityTuplizerFactory( this.getEntityTuplizerFactory() );
|
||||||
|
// settings.setComponentTuplizerFactory( this.getComponentTuplizerFactory() );
|
||||||
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map getNamedSQLQueries() {
|
public Map getNamedSQLQueries() {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.transaction.TransactionManagerLookup;
|
||||||
import org.hibernate.exception.SQLExceptionConverter;
|
import org.hibernate.exception.SQLExceptionConverter;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
|
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings that affect the behaviour of Hibernate at runtime.
|
* Settings that affect the behaviour of Hibernate at runtime.
|
||||||
|
@ -67,6 +68,8 @@ public final class Settings {
|
||||||
private boolean dataDefinitionInTransactionSupported;
|
private boolean dataDefinitionInTransactionSupported;
|
||||||
private boolean strictJPAQLCompliance;
|
private boolean strictJPAQLCompliance;
|
||||||
private boolean namedQueryStartupCheckingEnabled;
|
private boolean namedQueryStartupCheckingEnabled;
|
||||||
|
private EntityTuplizerFactory entityTuplizerFactory;
|
||||||
|
// private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907
|
||||||
// private BytecodeProvider bytecodeProvider;
|
// private BytecodeProvider bytecodeProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -257,6 +260,14 @@ public final class Settings {
|
||||||
return namedQueryStartupCheckingEnabled;
|
return namedQueryStartupCheckingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EntityTuplizerFactory getEntityTuplizerFactory() {
|
||||||
|
return entityTuplizerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public ComponentTuplizerFactory getComponentTuplizerFactory() {
|
||||||
|
// return componentTuplizerFactory;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
// package protected setters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// package protected setters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -440,6 +451,14 @@ public final class Settings {
|
||||||
this.namedQueryStartupCheckingEnabled = namedQueryStartupCheckingEnabled;
|
this.namedQueryStartupCheckingEnabled = namedQueryStartupCheckingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setEntityTuplizerFactory(EntityTuplizerFactory entityTuplizerFactory) {
|
||||||
|
this.entityTuplizerFactory = entityTuplizerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void setComponentTuplizerFactory(ComponentTuplizerFactory componentTuplizerFactory) {
|
||||||
|
// this.componentTuplizerFactory = componentTuplizerFactory;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
// public BytecodeProvider getBytecodeProvider() {
|
// public BytecodeProvider getBytecodeProvider() {
|
||||||
// return bytecodeProvider;
|
// return bytecodeProvider;
|
||||||
|
|
|
@ -5,8 +5,6 @@ import org.hibernate.tuple.Tuplizer;
|
||||||
import org.hibernate.mapping.Component;
|
import org.hibernate.mapping.Component;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.util.ReflectHelper;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -23,7 +21,8 @@ import java.io.Serializable;
|
||||||
*/
|
*/
|
||||||
class ComponentEntityModeToTuplizerMapping extends EntityModeToTuplizerMapping implements Serializable {
|
class ComponentEntityModeToTuplizerMapping extends EntityModeToTuplizerMapping implements Serializable {
|
||||||
|
|
||||||
private static final Class[] COMPONENT_TUP_CTOR_SIG = new Class[] { Component.class };
|
// todo : move this to SF per HHH-3517; also see HHH-1907 and ComponentMetamodel
|
||||||
|
private ComponentTuplizerFactory componentTuplizerFactory = new ComponentTuplizerFactory();
|
||||||
|
|
||||||
public ComponentEntityModeToTuplizerMapping(Component component) {
|
public ComponentEntityModeToTuplizerMapping(Component component) {
|
||||||
PersistentClass owner = component.getOwner();
|
PersistentClass owner = component.getOwner();
|
||||||
|
@ -35,24 +34,24 @@ class ComponentEntityModeToTuplizerMapping extends EntityModeToTuplizerMapping i
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the dynamic-map tuplizer...
|
// Build the dynamic-map tuplizer...
|
||||||
Tuplizer dynamicMapTuplizer = null;
|
Tuplizer dynamicMapTuplizer;
|
||||||
String tuplizerImpl = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.MAP );
|
String tuplizerClassName = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.MAP );
|
||||||
if ( tuplizerImpl == null ) {
|
if ( tuplizerClassName == null ) {
|
||||||
dynamicMapTuplizer = new DynamicMapComponentTuplizer( component );
|
dynamicMapTuplizer = componentTuplizerFactory.constructDefaultTuplizer( EntityMode.MAP, component );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dynamicMapTuplizer = buildComponentTuplizer( tuplizerImpl, component );
|
dynamicMapTuplizer = componentTuplizerFactory.constructTuplizer( tuplizerClassName, component );
|
||||||
}
|
}
|
||||||
|
|
||||||
// then the pojo tuplizer, using the dynamic-map tuplizer if no pojo representation is available
|
// then the pojo tuplizer, using the dynamic-map tuplizer if no pojo representation is available
|
||||||
tuplizerImpl = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.POJO );
|
tuplizerClassName = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.POJO );
|
||||||
Tuplizer pojoTuplizer = null;
|
Tuplizer pojoTuplizer;
|
||||||
if ( owner.hasPojoRepresentation() && component.hasPojoRepresentation() ) {
|
if ( owner.hasPojoRepresentation() && component.hasPojoRepresentation() ) {
|
||||||
if ( tuplizerImpl == null ) {
|
if ( tuplizerClassName == null ) {
|
||||||
pojoTuplizer = new PojoComponentTuplizer( component );
|
pojoTuplizer = componentTuplizerFactory.constructDefaultTuplizer( EntityMode.POJO, component );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pojoTuplizer = buildComponentTuplizer( tuplizerImpl, component );
|
pojoTuplizer = componentTuplizerFactory.constructTuplizer( tuplizerClassName, component );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -60,14 +59,14 @@ class ComponentEntityModeToTuplizerMapping extends EntityModeToTuplizerMapping i
|
||||||
}
|
}
|
||||||
|
|
||||||
// then dom4j tuplizer, if dom4j representation is available
|
// then dom4j tuplizer, if dom4j representation is available
|
||||||
Tuplizer dom4jTuplizer = null;
|
Tuplizer dom4jTuplizer;
|
||||||
tuplizerImpl = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.DOM4J );
|
tuplizerClassName = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.DOM4J );
|
||||||
if ( owner.hasDom4jRepresentation() ) {
|
if ( owner.hasDom4jRepresentation() ) {
|
||||||
if ( tuplizerImpl == null ) {
|
if ( tuplizerClassName == null ) {
|
||||||
dom4jTuplizer = new Dom4jComponentTuplizer( component );
|
dom4jTuplizer = componentTuplizerFactory.constructDefaultTuplizer( EntityMode.DOM4J, component );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dom4jTuplizer = buildComponentTuplizer( tuplizerImpl, component );
|
dom4jTuplizer = componentTuplizerFactory.constructTuplizer( tuplizerClassName, component );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -89,21 +88,12 @@ class ComponentEntityModeToTuplizerMapping extends EntityModeToTuplizerMapping i
|
||||||
if ( !userSuppliedTuplizerImpls.isEmpty() ) {
|
if ( !userSuppliedTuplizerImpls.isEmpty() ) {
|
||||||
Iterator itr = userSuppliedTuplizerImpls.entrySet().iterator();
|
Iterator itr = userSuppliedTuplizerImpls.entrySet().iterator();
|
||||||
while ( itr.hasNext() ) {
|
while ( itr.hasNext() ) {
|
||||||
Map.Entry entry = ( Map.Entry ) itr.next();
|
final Map.Entry entry = ( Map.Entry ) itr.next();
|
||||||
EntityMode entityMode = ( EntityMode ) entry.getKey();
|
final EntityMode entityMode = ( EntityMode ) entry.getKey();
|
||||||
ComponentTuplizer tuplizer = buildComponentTuplizer( ( String ) entry.getValue(), component );
|
final String userTuplizerClassName = ( String ) entry.getValue();
|
||||||
|
ComponentTuplizer tuplizer = componentTuplizerFactory.constructTuplizer( userTuplizerClassName, component );
|
||||||
addTuplizer( entityMode, tuplizer );
|
addTuplizer( entityMode, tuplizer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ComponentTuplizer buildComponentTuplizer(String tuplizerImpl, Component component) {
|
|
||||||
try {
|
|
||||||
Class implClass = ReflectHelper.classForName( tuplizerImpl );
|
|
||||||
return ( ComponentTuplizer ) implClass.getConstructor( COMPONENT_TUP_CTOR_SIG ).newInstance( new Object[] { component } );
|
|
||||||
}
|
|
||||||
catch( Throwable t ) {
|
|
||||||
throw new HibernateException( "Could not build tuplizer [" + tuplizerImpl + "]", t );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program 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 distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.tuple.component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.hibernate.util.FastHashMap;
|
||||||
|
import org.hibernate.util.ReflectHelper;
|
||||||
|
import org.hibernate.EntityMode;
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.mapping.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A registry allowing users to define the default {@link ComponentTuplizer} class to use per {@link EntityMode}.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class ComponentTuplizerFactory implements Serializable {
|
||||||
|
|
||||||
|
private static final Class[] COMPONENT_TUP_CTOR_SIG = new Class[] { Component.class };
|
||||||
|
|
||||||
|
private Map defaultImplClassByMode = buildBaseMapping();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method allowing registration of the tuplizer class to use as default for a particular entity-mode.
|
||||||
|
*
|
||||||
|
* @param entityMode The entity-mode for which to register the tuplizer class
|
||||||
|
* @param tuplizerClass The class to use as the default tuplizer for the given entity-mode.
|
||||||
|
*/
|
||||||
|
public void registerDefaultTuplizerClass(EntityMode entityMode, Class tuplizerClass) {
|
||||||
|
assert isComponentTuplizerImplementor( tuplizerClass )
|
||||||
|
: "Specified tuplizer class [" + tuplizerClass.getName() + "] does not implement " + ComponentTuplizer.class.getName();
|
||||||
|
assert hasProperConstructor( tuplizerClass )
|
||||||
|
: "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable";
|
||||||
|
|
||||||
|
defaultImplClassByMode.put( entityMode, tuplizerClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an instance of the given tuplizer class.
|
||||||
|
*
|
||||||
|
* @param tuplizerClassName The name of the tuplizer class to instantiate
|
||||||
|
* @param metadata The metadata for the component.
|
||||||
|
*
|
||||||
|
* @return The instantiated tuplizer
|
||||||
|
*
|
||||||
|
* @throws HibernateException If class name cannot be resolved to a class reference, or if the
|
||||||
|
* {@link Constructor#newInstance} call fails.
|
||||||
|
*/
|
||||||
|
public ComponentTuplizer constructTuplizer(String tuplizerClassName, Component metadata) {
|
||||||
|
try {
|
||||||
|
Class tuplizerClass = ReflectHelper.classForName( tuplizerClassName );
|
||||||
|
return constructTuplizer( tuplizerClass, metadata );
|
||||||
|
}
|
||||||
|
catch ( ClassNotFoundException e ) {
|
||||||
|
throw new HibernateException( "Could not locate specified tuplizer class [" + tuplizerClassName + "]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an instance of the given tuplizer class.
|
||||||
|
*
|
||||||
|
* @param tuplizerClass The tuplizer class to instantiate
|
||||||
|
* @param metadata The metadata for the component.
|
||||||
|
*
|
||||||
|
* @return The instantiated tuplizer
|
||||||
|
*
|
||||||
|
* @throws HibernateException if the {@link java.lang.reflect.Constructor#newInstance} call fails.
|
||||||
|
*/
|
||||||
|
public ComponentTuplizer constructTuplizer(Class tuplizerClass, Component metadata) {
|
||||||
|
Constructor ctor = getProperConstructor( tuplizerClass );
|
||||||
|
assert ctor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]";
|
||||||
|
try {
|
||||||
|
return ( ComponentTuplizer ) ctor.newInstance( new Object[] { metadata } );
|
||||||
|
}
|
||||||
|
catch ( Throwable t ) {
|
||||||
|
throw new HibernateException( "Unable to instantiate default tuplizer [" + tuplizerClass.getName() + "]", t );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct am instance of the default tuplizer for the given entity-mode.
|
||||||
|
*
|
||||||
|
* @param entityMode The entity mode for which to build a default tuplizer.
|
||||||
|
* @param metadata The metadata for the component.
|
||||||
|
*
|
||||||
|
* @return The instantiated tuplizer
|
||||||
|
*
|
||||||
|
* @throws HibernateException If no default tuplizer found for that entity-mode; may be re-thrown from
|
||||||
|
* {@link #constructTuplizer} too.
|
||||||
|
*/
|
||||||
|
public ComponentTuplizer constructDefaultTuplizer(EntityMode entityMode, Component metadata) {
|
||||||
|
Class tuplizerClass = ( Class ) defaultImplClassByMode.get( entityMode );
|
||||||
|
if ( tuplizerClass == null ) {
|
||||||
|
throw new HibernateException( "could not determine default tuplizer class to use [" + entityMode + "]" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return constructTuplizer( tuplizerClass, metadata );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isComponentTuplizerImplementor(Class tuplizerClass) {
|
||||||
|
return ReflectHelper.implementsInterface( tuplizerClass, ComponentTuplizer.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasProperConstructor(Class tuplizerClass) {
|
||||||
|
return getProperConstructor( tuplizerClass ) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Constructor getProperConstructor(Class clazz) {
|
||||||
|
Constructor ctor = null;
|
||||||
|
try {
|
||||||
|
ctor = clazz.getDeclaredConstructor( COMPONENT_TUP_CTOR_SIG );
|
||||||
|
if ( ! ReflectHelper.isPublic( ctor ) ) {
|
||||||
|
try {
|
||||||
|
// found a ctor, but it was not publicly accessible so try to request accessibility
|
||||||
|
ctor.setAccessible( true );
|
||||||
|
}
|
||||||
|
catch ( SecurityException e ) {
|
||||||
|
ctor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( NoSuchMethodException ignore ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map buildBaseMapping() {
|
||||||
|
Map map = new FastHashMap();
|
||||||
|
map.put( EntityMode.POJO, PojoComponentTuplizer.class );
|
||||||
|
map.put( EntityMode.DOM4J, Dom4jComponentTuplizer.class );
|
||||||
|
map.put( EntityMode.MAP, DynamicMapComponentTuplizer.class );
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,8 +4,6 @@ import org.hibernate.tuple.EntityModeToTuplizerMapping;
|
||||||
import org.hibernate.tuple.Tuplizer;
|
import org.hibernate.tuple.Tuplizer;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.util.ReflectHelper;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -22,8 +20,6 @@ import java.io.Serializable;
|
||||||
*/
|
*/
|
||||||
public class EntityEntityModeToTuplizerMapping extends EntityModeToTuplizerMapping implements Serializable {
|
public class EntityEntityModeToTuplizerMapping extends EntityModeToTuplizerMapping implements Serializable {
|
||||||
|
|
||||||
private static final Class[] ENTITY_TUP_CTOR_SIG = new Class[] { EntityMetamodel.class, PersistentClass.class };
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a EntityEntityModeToTuplizerMapping based on the given
|
* Instantiates a EntityEntityModeToTuplizerMapping based on the given
|
||||||
* entity mapping and metamodel definitions.
|
* entity mapping and metamodel definitions.
|
||||||
|
@ -32,6 +28,10 @@ public class EntityEntityModeToTuplizerMapping extends EntityModeToTuplizerMappi
|
||||||
* @param em The entity metamodel definition.
|
* @param em The entity metamodel definition.
|
||||||
*/
|
*/
|
||||||
public EntityEntityModeToTuplizerMapping(PersistentClass mappedEntity, EntityMetamodel em) {
|
public EntityEntityModeToTuplizerMapping(PersistentClass mappedEntity, EntityMetamodel em) {
|
||||||
|
final EntityTuplizerFactory entityTuplizerFactory = em.getSessionFactory()
|
||||||
|
.getSettings()
|
||||||
|
.getEntityTuplizerFactory();
|
||||||
|
|
||||||
// create our own copy of the user-supplied tuplizer impl map
|
// create our own copy of the user-supplied tuplizer impl map
|
||||||
Map userSuppliedTuplizerImpls = new HashMap();
|
Map userSuppliedTuplizerImpls = new HashMap();
|
||||||
if ( mappedEntity.getTuplizerMap() != null ) {
|
if ( mappedEntity.getTuplizerMap() != null ) {
|
||||||
|
@ -39,24 +39,24 @@ public class EntityEntityModeToTuplizerMapping extends EntityModeToTuplizerMappi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the dynamic-map tuplizer...
|
// Build the dynamic-map tuplizer...
|
||||||
Tuplizer dynamicMapTuplizer = null;
|
Tuplizer dynamicMapTuplizer;
|
||||||
String tuplizerImpl = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.MAP );
|
String tuplizerImplClassName = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.MAP );
|
||||||
if ( tuplizerImpl == null ) {
|
if ( tuplizerImplClassName == null ) {
|
||||||
dynamicMapTuplizer = new DynamicMapEntityTuplizer( em, mappedEntity );
|
dynamicMapTuplizer = entityTuplizerFactory.constructDefaultTuplizer( EntityMode.MAP, em, mappedEntity );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dynamicMapTuplizer = buildEntityTuplizer( tuplizerImpl, mappedEntity, em );
|
dynamicMapTuplizer = entityTuplizerFactory.constructTuplizer( tuplizerImplClassName, em, mappedEntity );
|
||||||
}
|
}
|
||||||
|
|
||||||
// then the pojo tuplizer, using the dynamic-map tuplizer if no pojo representation is available
|
// then the pojo tuplizer, using the dynamic-map tuplizer if no pojo representation is available
|
||||||
Tuplizer pojoTuplizer = null;
|
Tuplizer pojoTuplizer;
|
||||||
tuplizerImpl = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.POJO );
|
tuplizerImplClassName = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.POJO );
|
||||||
if ( mappedEntity.hasPojoRepresentation() ) {
|
if ( mappedEntity.hasPojoRepresentation() ) {
|
||||||
if ( tuplizerImpl == null ) {
|
if ( tuplizerImplClassName == null ) {
|
||||||
pojoTuplizer = new PojoEntityTuplizer( em, mappedEntity );
|
pojoTuplizer = entityTuplizerFactory.constructDefaultTuplizer( EntityMode.POJO, em, mappedEntity );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pojoTuplizer = buildEntityTuplizer( tuplizerImpl, mappedEntity, em );
|
pojoTuplizer = entityTuplizerFactory.constructTuplizer( tuplizerImplClassName, em, mappedEntity );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -64,14 +64,14 @@ public class EntityEntityModeToTuplizerMapping extends EntityModeToTuplizerMappi
|
||||||
}
|
}
|
||||||
|
|
||||||
// then dom4j tuplizer, if dom4j representation is available
|
// then dom4j tuplizer, if dom4j representation is available
|
||||||
Tuplizer dom4jTuplizer = null;
|
Tuplizer dom4jTuplizer;
|
||||||
tuplizerImpl = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.DOM4J );
|
tuplizerImplClassName = ( String ) userSuppliedTuplizerImpls.remove( EntityMode.DOM4J );
|
||||||
if ( mappedEntity.hasDom4jRepresentation() ) {
|
if ( mappedEntity.hasDom4jRepresentation() ) {
|
||||||
if ( tuplizerImpl == null ) {
|
if ( tuplizerImplClassName == null ) {
|
||||||
dom4jTuplizer = new Dom4jEntityTuplizer( em, mappedEntity );
|
dom4jTuplizer = entityTuplizerFactory.constructDefaultTuplizer( EntityMode.DOM4J, em, mappedEntity );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dom4jTuplizer = buildEntityTuplizer( tuplizerImpl, mappedEntity, em );
|
dom4jTuplizer = entityTuplizerFactory.constructTuplizer( tuplizerImplClassName, em, mappedEntity );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -93,21 +93,12 @@ public class EntityEntityModeToTuplizerMapping extends EntityModeToTuplizerMappi
|
||||||
if ( !userSuppliedTuplizerImpls.isEmpty() ) {
|
if ( !userSuppliedTuplizerImpls.isEmpty() ) {
|
||||||
Iterator itr = userSuppliedTuplizerImpls.entrySet().iterator();
|
Iterator itr = userSuppliedTuplizerImpls.entrySet().iterator();
|
||||||
while ( itr.hasNext() ) {
|
while ( itr.hasNext() ) {
|
||||||
Map.Entry entry = ( Map.Entry ) itr.next();
|
final Map.Entry entry = ( Map.Entry ) itr.next();
|
||||||
EntityMode entityMode = ( EntityMode ) entry.getKey();
|
final EntityMode entityMode = ( EntityMode ) entry.getKey();
|
||||||
EntityTuplizer tuplizer = buildEntityTuplizer( ( String ) entry.getValue(), mappedEntity, em );
|
final String tuplizerClassName = ( String ) entry.getValue();
|
||||||
|
final EntityTuplizer tuplizer = entityTuplizerFactory.constructTuplizer( tuplizerClassName, em, mappedEntity );
|
||||||
addTuplizer( entityMode, tuplizer );
|
addTuplizer( entityMode, tuplizer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EntityTuplizer buildEntityTuplizer(String className, PersistentClass pc, EntityMetamodel em) {
|
|
||||||
try {
|
|
||||||
Class implClass = ReflectHelper.classForName( className );
|
|
||||||
return ( EntityTuplizer ) implClass.getConstructor( ENTITY_TUP_CTOR_SIG ).newInstance( new Object[] { em, pc } );
|
|
||||||
}
|
|
||||||
catch( Throwable t ) {
|
|
||||||
throw new HibernateException( "Could not build tuplizer [" + className + "]", t );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,4 +215,4 @@ public interface EntityTuplizer extends Tuplizer {
|
||||||
* @throws HibernateException If we are unable to determine an entity-name within the inheritence hierarchy.
|
* @throws HibernateException If we are unable to determine an entity-name within the inheritence hierarchy.
|
||||||
*/
|
*/
|
||||||
public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory);
|
public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory);
|
||||||
}
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program 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 distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.tuple.entity;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
||||||
|
import org.hibernate.util.FastHashMap;
|
||||||
|
import org.hibernate.util.ReflectHelper;
|
||||||
|
import org.hibernate.EntityMode;
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A registry allowing users to define the default {@link EntityTuplizer} class to use per {@link EntityMode}.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class EntityTuplizerFactory implements Serializable {
|
||||||
|
|
||||||
|
public static final Class[] ENTITY_TUP_CTOR_SIG = new Class[] { EntityMetamodel.class, PersistentClass.class };
|
||||||
|
|
||||||
|
private Map defaultImplClassByMode = buildBaseMapping();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method allowing registration of the tuplizer class to use as default for a particular entity-mode.
|
||||||
|
*
|
||||||
|
* @param entityMode The entity-mode for which to register the tuplizer class
|
||||||
|
* @param tuplizerClass The class to use as the default tuplizer for the given entity-mode.
|
||||||
|
*/
|
||||||
|
public void registerDefaultTuplizerClass(EntityMode entityMode, Class tuplizerClass) {
|
||||||
|
assert isEntityTuplizerImplementor( tuplizerClass )
|
||||||
|
: "Specified tuplizer class [" + tuplizerClass.getName() + "] does not implement " + EntityTuplizer.class.getName();
|
||||||
|
assert hasProperConstructor( tuplizerClass )
|
||||||
|
: "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable";
|
||||||
|
|
||||||
|
defaultImplClassByMode.put( entityMode, tuplizerClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an instance of the given tuplizer class.
|
||||||
|
*
|
||||||
|
* @param tuplizerClassName The name of the tuplizer class to instantiate
|
||||||
|
* @param metamodel The metadata for the entity.
|
||||||
|
* @param persistentClass The mapping info for the entity.
|
||||||
|
*
|
||||||
|
* @return The instantiated tuplizer
|
||||||
|
*
|
||||||
|
* @throws HibernateException If class name cannot be resolved to a class reference, or if the
|
||||||
|
* {@link Constructor#newInstance} call fails.
|
||||||
|
*/
|
||||||
|
public EntityTuplizer constructTuplizer(
|
||||||
|
String tuplizerClassName,
|
||||||
|
EntityMetamodel metamodel,
|
||||||
|
PersistentClass persistentClass) {
|
||||||
|
try {
|
||||||
|
Class tuplizerClass = ReflectHelper.classForName( tuplizerClassName );
|
||||||
|
return constructTuplizer( tuplizerClass, metamodel, persistentClass );
|
||||||
|
}
|
||||||
|
catch ( ClassNotFoundException e ) {
|
||||||
|
throw new HibernateException( "Could not locate specified tuplizer class [" + tuplizerClassName + "]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an instance of the given tuplizer class.
|
||||||
|
*
|
||||||
|
* @param tuplizerClass The tuplizer class to instantiate
|
||||||
|
* @param metamodel The metadata for the entity.
|
||||||
|
* @param persistentClass The mapping info for the entity.
|
||||||
|
*
|
||||||
|
* @return The instantiated tuplizer
|
||||||
|
*
|
||||||
|
* @throws HibernateException if the {@link Constructor#newInstance} call fails.
|
||||||
|
*/
|
||||||
|
public EntityTuplizer constructTuplizer(
|
||||||
|
Class tuplizerClass,
|
||||||
|
EntityMetamodel metamodel,
|
||||||
|
PersistentClass persistentClass) {
|
||||||
|
Constructor ctor = getProperConstructor( tuplizerClass );
|
||||||
|
assert ctor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]";
|
||||||
|
try {
|
||||||
|
return ( EntityTuplizer ) ctor.newInstance( new Object[] { metamodel, persistentClass } );
|
||||||
|
}
|
||||||
|
catch ( Throwable t ) {
|
||||||
|
throw new HibernateException( "Unable to instantiate default tuplizer [" + tuplizerClass.getName() + "]", t );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct am instance of the default tuplizer for the given entity-mode.
|
||||||
|
*
|
||||||
|
* @param entityMode The entity mode for which to build a default tuplizer.
|
||||||
|
* @param metamodel The entity metadata.
|
||||||
|
* @param persistentClass The entity mapping info.
|
||||||
|
*
|
||||||
|
* @return The instantiated tuplizer
|
||||||
|
*
|
||||||
|
* @throws HibernateException If no default tuplizer found for that entity-mode; may be re-thrown from
|
||||||
|
* {@link #constructTuplizer} too.
|
||||||
|
*/
|
||||||
|
public EntityTuplizer constructDefaultTuplizer(
|
||||||
|
EntityMode entityMode,
|
||||||
|
EntityMetamodel metamodel,
|
||||||
|
PersistentClass persistentClass) {
|
||||||
|
Class tuplizerClass = ( Class ) defaultImplClassByMode.get( entityMode );
|
||||||
|
if ( tuplizerClass == null ) {
|
||||||
|
throw new HibernateException( "could not determine default tuplizer class to use [" + entityMode + "]" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return constructTuplizer( tuplizerClass, metamodel, persistentClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEntityTuplizerImplementor(Class tuplizerClass) {
|
||||||
|
return ReflectHelper.implementsInterface( tuplizerClass, EntityTuplizer.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasProperConstructor(Class tuplizerClass) {
|
||||||
|
return getProperConstructor( tuplizerClass ) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Constructor getProperConstructor(Class clazz) {
|
||||||
|
Constructor ctor = null;
|
||||||
|
try {
|
||||||
|
ctor = clazz.getDeclaredConstructor( ENTITY_TUP_CTOR_SIG );
|
||||||
|
if ( ! ReflectHelper.isPublic( ctor ) ) {
|
||||||
|
try {
|
||||||
|
// found a ctor, but it was not publicly accessible so try to request accessibility
|
||||||
|
ctor.setAccessible( true );
|
||||||
|
}
|
||||||
|
catch ( SecurityException e ) {
|
||||||
|
ctor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( NoSuchMethodException ignore ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map buildBaseMapping() {
|
||||||
|
Map map = new FastHashMap();
|
||||||
|
map.put( EntityMode.POJO, PojoEntityTuplizer.class );
|
||||||
|
map.put( EntityMode.DOM4J, Dom4jEntityTuplizer.class );
|
||||||
|
map.put( EntityMode.MAP, DynamicMapEntityTuplizer.class );
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,90 +16,132 @@ import org.hibernate.property.PropertyAccessor;
|
||||||
import org.hibernate.type.PrimitiveType;
|
import org.hibernate.type.PrimitiveType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for various reflection operations.
|
||||||
|
*
|
||||||
|
* @author Gavin King
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
public final class ReflectHelper {
|
public final class ReflectHelper {
|
||||||
|
|
||||||
//TODO: this dependency is kinda Bad
|
//TODO: this dependency is kinda Bad
|
||||||
private static final PropertyAccessor BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor();
|
private static final PropertyAccessor BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor();
|
||||||
private static final PropertyAccessor DIRECT_PROPERTY_ACCESSOR = new DirectPropertyAccessor();
|
private static final PropertyAccessor DIRECT_PROPERTY_ACCESSOR = new DirectPropertyAccessor();
|
||||||
|
|
||||||
private static final Class[] NO_CLASSES = new Class[0];
|
public static final Class[] NO_PARAM_SIGNATURE = new Class[0];
|
||||||
private static final Class[] OBJECT = new Class[] { Object.class };
|
public static final Object[] NO_PARAMS = new Object[0];
|
||||||
private static final Method OBJECT_EQUALS;
|
|
||||||
private static final Class[] NO_PARAM = new Class[] { };
|
|
||||||
|
|
||||||
|
public static final Class[] SINGLE_OBJECT_PARAM_SIGNATURE = new Class[] { Object.class };
|
||||||
|
|
||||||
|
private static final Method OBJECT_EQUALS;
|
||||||
private static final Method OBJECT_HASHCODE;
|
private static final Method OBJECT_HASHCODE;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Method eq;
|
Method eq;
|
||||||
Method hash;
|
Method hash;
|
||||||
try {
|
try {
|
||||||
eq = Object.class.getMethod("equals", OBJECT);
|
eq = extractEqualsMethod( Object.class );
|
||||||
hash = Object.class.getMethod("hashCode", NO_PARAM);
|
hash = extractHashCodeMethod( Object.class );
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch ( Exception e ) {
|
||||||
throw new AssertionFailure("Could not find Object.equals() or Object.hashCode()", e);
|
throw new AssertionFailure( "Could not find Object.equals() or Object.hashCode()", e );
|
||||||
}
|
}
|
||||||
OBJECT_EQUALS = eq;
|
OBJECT_EQUALS = eq;
|
||||||
OBJECT_HASHCODE = hash;
|
OBJECT_HASHCODE = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disallow instantiation of ReflectHelper.
|
||||||
|
*/
|
||||||
|
private ReflectHelper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulation of getting hold of a class's {@link Object#equals equals} method.
|
||||||
|
*
|
||||||
|
* @param clazz The class from which to extract the equals method.
|
||||||
|
* @return The equals method reference
|
||||||
|
* @throws NoSuchMethodException Should indicate an attempt to extract equals method from interface.
|
||||||
|
*/
|
||||||
|
public static Method extractEqualsMethod(Class clazz) throws NoSuchMethodException {
|
||||||
|
return clazz.getMethod( "equals", SINGLE_OBJECT_PARAM_SIGNATURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulation of getting hold of a class's {@link Object#hashCode hashCode} method.
|
||||||
|
*
|
||||||
|
* @param clazz The class from which to extract the hashCode method.
|
||||||
|
* @return The hashCode method reference
|
||||||
|
* @throws NoSuchMethodException Should indicate an attempt to extract hashCode method from interface.
|
||||||
|
*/
|
||||||
|
public static Method extractHashCodeMethod(Class clazz) throws NoSuchMethodException {
|
||||||
|
return clazz.getMethod( "hashCode", NO_PARAM_SIGNATURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the given class defines an {@link Object#equals} override.
|
||||||
|
*
|
||||||
|
* @param clazz The class to check
|
||||||
|
* @return True if clazz defines an equals override.
|
||||||
|
*/
|
||||||
public static boolean overridesEquals(Class clazz) {
|
public static boolean overridesEquals(Class clazz) {
|
||||||
Method equals;
|
Method equals;
|
||||||
try {
|
try {
|
||||||
equals = clazz.getMethod("equals", OBJECT);
|
equals = extractEqualsMethod( clazz );
|
||||||
}
|
}
|
||||||
catch (NoSuchMethodException nsme) {
|
catch ( NoSuchMethodException nsme ) {
|
||||||
return false; //its an interface so we can't really tell anything...
|
return false; //its an interface so we can't really tell anything...
|
||||||
}
|
}
|
||||||
return !OBJECT_EQUALS.equals(equals);
|
return !OBJECT_EQUALS.equals( equals );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the given class defines a {@link Object#hashCode} override.
|
||||||
|
*
|
||||||
|
* @param clazz The class to check
|
||||||
|
* @return True if clazz defines an hashCode override.
|
||||||
|
*/
|
||||||
public static boolean overridesHashCode(Class clazz) {
|
public static boolean overridesHashCode(Class clazz) {
|
||||||
Method hashCode;
|
Method hashCode;
|
||||||
try {
|
try {
|
||||||
hashCode = clazz.getMethod("hashCode", NO_PARAM);
|
hashCode = extractHashCodeMethod( clazz );
|
||||||
}
|
}
|
||||||
catch (NoSuchMethodException nsme) {
|
catch ( NoSuchMethodException nsme ) {
|
||||||
return false; //its an interface so we can't really tell anything...
|
return false; //its an interface so we can't really tell anything...
|
||||||
}
|
}
|
||||||
return !OBJECT_HASHCODE.equals(hashCode);
|
return !OBJECT_HASHCODE.equals( hashCode );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Class reflectedPropertyClass(String className, String name) throws MappingException {
|
/**
|
||||||
try {
|
* Determine if the given class implements the given interface.
|
||||||
Class clazz = ReflectHelper.classForName(className);
|
*
|
||||||
return getter(clazz, name).getReturnType();
|
* @param clazz The class to check
|
||||||
}
|
* @param intf The interface to check it against.
|
||||||
catch (ClassNotFoundException cnfe) {
|
* @return True if the class does implement the interface, false otherwise.
|
||||||
throw new MappingException("class " + className + " not found while looking for property: " + name, cnfe);
|
*/
|
||||||
}
|
public static boolean implementsInterface(Class clazz, Class intf) {
|
||||||
}
|
assert intf.isInterface() : "Interface to check was not an interface";
|
||||||
|
|
||||||
private static Getter getter(Class clazz, String name) throws MappingException {
|
Class[] interfaces = clazz.getInterfaces();
|
||||||
try {
|
for ( int i = 0; i < interfaces.length; i++ ) {
|
||||||
return BASIC_PROPERTY_ACCESSOR.getGetter(clazz, name);
|
if ( intf.isAssignableFrom( interfaces[i] ) ) {
|
||||||
}
|
return true;
|
||||||
catch (PropertyNotFoundException pnfe) {
|
|
||||||
return DIRECT_PROPERTY_ACCESSOR.getGetter(clazz, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Getter getGetter(Class theClass, String name) throws MappingException {
|
|
||||||
return BASIC_PROPERTY_ACCESSOR.getGetter(theClass, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Class classForName(String name) throws ClassNotFoundException {
|
|
||||||
try {
|
|
||||||
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
if ( contextClassLoader != null ) {
|
|
||||||
return contextClassLoader.loadClass(name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ( Throwable t ) {
|
return false;
|
||||||
}
|
|
||||||
return Class.forName( name );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform resolution of a class name.
|
||||||
|
* <p/>
|
||||||
|
* Here we first check the context classloader, if one, before delegating to
|
||||||
|
* {@link Class#forName(String, boolean, ClassLoader)} using the caller's classloader
|
||||||
|
*
|
||||||
|
* @param name The class name
|
||||||
|
* @param caller The class from which this call originated (in order to access that class's loader).
|
||||||
|
* @return The class reference.
|
||||||
|
* @throws ClassNotFoundException From {@link Class#forName(String, boolean, ClassLoader)}.
|
||||||
|
*/
|
||||||
public static Class classForName(String name, Class caller) throws ClassNotFoundException {
|
public static Class classForName(String name, Class caller) throws ClassNotFoundException {
|
||||||
try {
|
try {
|
||||||
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
@ -107,15 +149,101 @@ public final class ReflectHelper {
|
||||||
return contextClassLoader.loadClass( name );
|
return contextClassLoader.loadClass( name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ( Throwable e ) {
|
catch ( Throwable ignore ) {
|
||||||
}
|
}
|
||||||
return Class.forName( name, true, caller.getClassLoader() );
|
return Class.forName( name, true, caller.getClassLoader() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform resolution of a class name.
|
||||||
|
* <p/>
|
||||||
|
* Same as {@link #classForName(String, Class)} except that here we delegate to
|
||||||
|
* {@link Class#forName(String)} if the context classloader lookup is unsuccessful.
|
||||||
|
*
|
||||||
|
* @param name The class name
|
||||||
|
* @return The class reference.
|
||||||
|
* @throws ClassNotFoundException From {@link Class#forName(String)}.
|
||||||
|
*/
|
||||||
|
public static Class classForName(String name) throws ClassNotFoundException {
|
||||||
|
try {
|
||||||
|
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
if ( contextClassLoader != null ) {
|
||||||
|
return contextClassLoader.loadClass(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( Throwable ignore ) {
|
||||||
|
}
|
||||||
|
return Class.forName( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this member publicly accessible.
|
||||||
|
* <p/>
|
||||||
|
* Short-hand for {@link #isPublic(Class, Member)} passing the member + {@link Member#getDeclaringClass()}
|
||||||
|
*
|
||||||
|
* @param member The member to check
|
||||||
|
* @return True if the member is publicly accessible.
|
||||||
|
*/
|
||||||
|
public static boolean isPublic(Member member) {
|
||||||
|
return isPublic( member.getDeclaringClass(), member );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this member publicly accessible.
|
||||||
|
*
|
||||||
|
* @param clazz The class which defines the member
|
||||||
|
* @param member The memeber.
|
||||||
|
* @return True if the member is publicly accessible, false otherwise.
|
||||||
|
*/
|
||||||
public static boolean isPublic(Class clazz, Member member) {
|
public static boolean isPublic(Class clazz, Member member) {
|
||||||
return Modifier.isPublic( member.getModifiers() ) && Modifier.isPublic( clazz.getModifiers() );
|
return Modifier.isPublic( member.getModifiers() ) && Modifier.isPublic( clazz.getModifiers() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to resolve the specified property type through reflection.
|
||||||
|
*
|
||||||
|
* @param className The name of the class owning the property.
|
||||||
|
* @param name The name of the property.
|
||||||
|
* @return The type of the property.
|
||||||
|
* @throws MappingException Indicates we were unable to locate the property.
|
||||||
|
*/
|
||||||
|
public static Class reflectedPropertyClass(String className, String name) throws MappingException {
|
||||||
|
try {
|
||||||
|
Class clazz = ReflectHelper.classForName( className );
|
||||||
|
return getter( clazz, name ).getReturnType();
|
||||||
|
}
|
||||||
|
catch ( ClassNotFoundException cnfe ) {
|
||||||
|
throw new MappingException( "class " + className + " not found while looking for property: " + name, cnfe );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Getter getter(Class clazz, String name) throws MappingException {
|
||||||
|
try {
|
||||||
|
return BASIC_PROPERTY_ACCESSOR.getGetter( clazz, name );
|
||||||
|
}
|
||||||
|
catch ( PropertyNotFoundException pnfe ) {
|
||||||
|
return DIRECT_PROPERTY_ACCESSOR.getGetter( clazz, name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directly retrieve the {@link Getter} reference via the {@link BasicPropertyAccessor}.
|
||||||
|
*
|
||||||
|
* @param theClass The class owning the property
|
||||||
|
* @param name The name of the property
|
||||||
|
* @return The getter.
|
||||||
|
* @throws MappingException Indicates we were unable to locate the property.
|
||||||
|
*/
|
||||||
|
public static Getter getGetter(Class theClass, String name) throws MappingException {
|
||||||
|
return BASIC_PROPERTY_ACCESSOR.getGetter( theClass, name );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a constant to its actual value.
|
||||||
|
*
|
||||||
|
* @param name The name
|
||||||
|
* @return The value
|
||||||
|
*/
|
||||||
public static Object getConstantValue(String name) {
|
public static Object getConstantValue(String name) {
|
||||||
Class clazz;
|
Class clazz;
|
||||||
try {
|
try {
|
||||||
|
@ -125,61 +253,90 @@ public final class ReflectHelper {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return clazz.getField( StringHelper.unqualify( name ) ).get(null);
|
return clazz.getField( StringHelper.unqualify( name ) ).get( null );
|
||||||
}
|
}
|
||||||
catch ( Throwable t ) {
|
catch ( Throwable t ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the default (no arg) constructor from the given class.
|
||||||
|
*
|
||||||
|
* @param clazz The class for which to retrieve the default ctor.
|
||||||
|
* @return The default constructor.
|
||||||
|
* @throws PropertyNotFoundException Indicates there was not publicly accessible, no-arg constructor (todo : why PropertyNotFoundException???)
|
||||||
|
*/
|
||||||
public static Constructor getDefaultConstructor(Class clazz) throws PropertyNotFoundException {
|
public static Constructor getDefaultConstructor(Class clazz) throws PropertyNotFoundException {
|
||||||
|
if ( isAbstractClass( clazz ) ) {
|
||||||
if ( isAbstractClass(clazz) ) return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Constructor constructor = clazz.getDeclaredConstructor(NO_CLASSES);
|
Constructor constructor = clazz.getDeclaredConstructor( NO_PARAM_SIGNATURE );
|
||||||
if ( !isPublic(clazz, constructor) ) {
|
if ( !isPublic( clazz, constructor ) ) {
|
||||||
constructor.setAccessible(true);
|
constructor.setAccessible( true );
|
||||||
}
|
}
|
||||||
return constructor;
|
return constructor;
|
||||||
}
|
}
|
||||||
catch (NoSuchMethodException nme) {
|
catch ( NoSuchMethodException nme ) {
|
||||||
throw new PropertyNotFoundException(
|
throw new PropertyNotFoundException(
|
||||||
"Object class " + clazz.getName() +
|
"Object class [" + clazz.getName() + "] must declare a default (no-argument) constructor"
|
||||||
" must declare a default (no-argument) constructor"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the given class is declared abstract.
|
||||||
|
*
|
||||||
|
* @param clazz The class to check.
|
||||||
|
* @return True if the class is abstract, false otherwise.
|
||||||
|
*/
|
||||||
public static boolean isAbstractClass(Class clazz) {
|
public static boolean isAbstractClass(Class clazz) {
|
||||||
int modifier = clazz.getModifiers();
|
int modifier = clazz.getModifiers();
|
||||||
return Modifier.isAbstract(modifier) || Modifier.isInterface(modifier);
|
return Modifier.isAbstract(modifier) || Modifier.isInterface(modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine is the given class is declared final.
|
||||||
|
*
|
||||||
|
* @param clazz The class to check.
|
||||||
|
* @return True if the class is final, flase otherwise.
|
||||||
|
*/
|
||||||
public static boolean isFinalClass(Class clazz) {
|
public static boolean isFinalClass(Class clazz) {
|
||||||
return Modifier.isFinal( clazz.getModifiers() );
|
return Modifier.isFinal( clazz.getModifiers() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a constructor for the given class, with arguments matching the specified Hibernate mapping
|
||||||
|
* {@link Type types}.
|
||||||
|
*
|
||||||
|
* @param clazz The class needing instantiation
|
||||||
|
* @param types The types representing the required ctor param signature
|
||||||
|
* @return The matching constructor.
|
||||||
|
* @throws PropertyNotFoundException Indicates we could not locate an appropriate constructor (todo : again with PropertyNotFoundException???)
|
||||||
|
*/
|
||||||
public static Constructor getConstructor(Class clazz, Type[] types) throws PropertyNotFoundException {
|
public static Constructor getConstructor(Class clazz, Type[] types) throws PropertyNotFoundException {
|
||||||
final Constructor[] candidates = clazz.getConstructors();
|
final Constructor[] candidates = clazz.getConstructors();
|
||||||
for ( int i=0; i<candidates.length; i++ ) {
|
for ( int i = 0; i < candidates.length; i++ ) {
|
||||||
final Constructor constructor = candidates[i];
|
final Constructor constructor = candidates[i];
|
||||||
final Class[] params = constructor.getParameterTypes();
|
final Class[] params = constructor.getParameterTypes();
|
||||||
if ( params.length==types.length ) {
|
if ( params.length == types.length ) {
|
||||||
boolean found = true;
|
boolean found = true;
|
||||||
for ( int j=0; j<params.length; j++ ) {
|
for ( int j = 0; j < params.length; j++ ) {
|
||||||
final boolean ok = params[j].isAssignableFrom( types[j].getReturnedClass() ) || (
|
final boolean ok = params[j].isAssignableFrom( types[j].getReturnedClass() ) || (
|
||||||
types[j] instanceof PrimitiveType &&
|
types[j] instanceof PrimitiveType &&
|
||||||
params[j] == ( (PrimitiveType) types[j] ).getPrimitiveClass()
|
params[j] == ( ( PrimitiveType ) types[j] ).getPrimitiveClass()
|
||||||
);
|
);
|
||||||
if (!ok) {
|
if ( !ok ) {
|
||||||
found = false;
|
found = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found) {
|
if ( found ) {
|
||||||
if ( !isPublic(clazz, constructor) ) constructor.setAccessible(true);
|
if ( !isPublic( clazz, constructor ) ) {
|
||||||
|
constructor.setAccessible( true );
|
||||||
|
}
|
||||||
return constructor;
|
return constructor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,6 +353,4 @@ public final class ReflectHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReflectHelper() {}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
<hibernate-mapping package="org.hibernate.test.dynamicentity">
|
<hibernate-mapping package="org.hibernate.test.dynamicentity">
|
||||||
|
|
||||||
<class name="Person" table="t_person" discriminator-value="person" abstract="false">
|
<class name="Person" table="t_person" discriminator-value="person" abstract="false">
|
||||||
<tuplizer class="org.hibernate.test.dynamicentity.tuplizer2.MyEntityTuplizer" entity-mode="pojo"/>
|
|
||||||
<id name="id">
|
<id name="id">
|
||||||
<generator class="native"/>
|
<generator class="native"/>
|
||||||
</id>
|
</id>
|
||||||
|
@ -46,13 +45,11 @@
|
||||||
</set>
|
</set>
|
||||||
|
|
||||||
<subclass name="Customer" discriminator-value="customer" abstract="false">
|
<subclass name="Customer" discriminator-value="customer" abstract="false">
|
||||||
<tuplizer class="org.hibernate.test.dynamicentity.tuplizer2.MyEntityTuplizer" entity-mode="pojo"/>
|
|
||||||
<many-to-one name="company" cascade="none" column="comp_id"/>
|
<many-to-one name="company" cascade="none" column="comp_id"/>
|
||||||
</subclass>
|
</subclass>
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
<class name="Company" table="t_company" abstract="false">
|
<class name="Company" table="t_company" abstract="false">
|
||||||
<tuplizer class="org.hibernate.test.dynamicentity.tuplizer2.MyEntityTuplizer" entity-mode="pojo"/>
|
|
||||||
<id name="id">
|
<id name="id">
|
||||||
<generator class="native"/>
|
<generator class="native"/>
|
||||||
</id>
|
</id>
|
||||||
|
@ -60,7 +57,6 @@
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
<class name="Address" table="t_address" abstract="false">
|
<class name="Address" table="t_address" abstract="false">
|
||||||
<tuplizer class="org.hibernate.test.dynamicentity.tuplizer2.MyEntityTuplizer" entity-mode="pojo"/>
|
|
||||||
<id name="id">
|
<id name="id">
|
||||||
<generator class="native"/>
|
<generator class="native"/>
|
||||||
</id>
|
</id>
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.test.dynamicentity.Address;
|
||||||
import org.hibernate.test.dynamicentity.Person;
|
import org.hibernate.test.dynamicentity.Person;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.junit.functional.FunctionalTestCase;
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||||
|
@ -61,6 +62,7 @@ public class ImprovedTuplizerDynamicEntityTest extends FunctionalTestCase {
|
||||||
|
|
||||||
public void configure(Configuration cfg) {
|
public void configure(Configuration cfg) {
|
||||||
super.configure( cfg );
|
super.configure( cfg );
|
||||||
|
cfg.getEntityTuplizerFactory().registerDefaultTuplizerClass( EntityMode.POJO, MyEntityTuplizer.class );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TestSuite suite() {
|
public static TestSuite suite() {
|
||||||
|
|
Loading…
Reference in New Issue