1 package org.hibernate.tuple; 3 4 import java.lang.reflect.Method ; 5 import java.lang.reflect.Modifier ; 6 import java.util.HashSet ; 7 import java.util.Iterator ; 8 import java.util.Map ; 9 import java.util.Set ; 10 11 import net.sf.cglib.beans.BulkBean; 12 import net.sf.cglib.reflect.FastClass; 13 import net.sf.cglib.transform.impl.InterceptFieldEnabled; 14 15 import org.apache.commons.logging.Log; 16 import org.apache.commons.logging.LogFactory; 17 import org.hibernate.EntityMode; 18 import org.hibernate.HibernateException; 19 import org.hibernate.MappingException; 20 import org.hibernate.PropertyAccessException; 21 import org.hibernate.cfg.Environment; 22 import org.hibernate.classic.Lifecycle; 23 import org.hibernate.classic.Validatable; 24 import org.hibernate.engine.SessionImplementor; 25 import org.hibernate.intercept.FieldInterceptor; 26 import org.hibernate.mapping.PersistentClass; 27 import org.hibernate.mapping.Property; 28 import org.hibernate.mapping.Subclass; 29 import org.hibernate.property.Getter; 30 import org.hibernate.property.Setter; 31 import org.hibernate.proxy.CGLIBProxyFactory; 32 import org.hibernate.proxy.HibernateProxy; 33 import org.hibernate.proxy.ProxyFactory; 34 import org.hibernate.type.AbstractComponentType; 35 import org.hibernate.util.ReflectHelper; 36 37 42 public class PojoEntityTuplizer extends AbstractEntityTuplizer { 43 44 static final Log log = LogFactory.getLog( PojoEntityTuplizer.class ); 45 46 private final Class mappedClass; 47 private final Class proxyInterface; 48 private final boolean lifecycleImplementor; 49 private final boolean validatableImplementor; 50 private final Set lazyPropertyNames = new HashSet (); 51 private BulkBean optimizer; 52 private FastClass fastClass; 53 54 public PojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) { 55 super( entityMetamodel, mappedEntity ); 56 this.mappedClass = mappedEntity.getMappedClass(); 57 this.proxyInterface = mappedEntity.getProxyInterface(); 58 this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass ); 59 this.validatableImplementor = Validatable.class.isAssignableFrom( mappedClass ); 60 61 Iterator iter = mappedEntity.getPropertyClosureIterator(); 62 while ( iter.hasNext() ) { 63 Property property = (Property) iter.next(); 64 if ( property.isLazy() ) { 65 lazyPropertyNames.add( property.getName() ); 66 } 67 } 68 69 String [] getterNames = new String [propertySpan]; 70 String [] setterNames = new String [propertySpan]; 71 Class [] propTypes = new Class [propertySpan]; 72 for ( int i = 0; i < propertySpan; i++ ) { 73 getterNames[i] = getters[i].getMethodName(); 74 setterNames[i] = setters[i].getMethodName(); 75 propTypes[i] = getters[i].getReturnType(); 76 } 77 78 if ( hasCustomAccessors || !Environment.useReflectionOptimizer() ) { 79 fastClass = null; 80 optimizer = null; 81 } 82 else { 83 fastClass = ReflectHelper.getFastClass( mappedClass ); 84 optimizer = ReflectHelper.getBulkBean( mappedClass, getterNames, setterNames, propTypes, fastClass ); 85 if (optimizer==null) fastClass = null; 86 } 87 88 } 89 90 protected ProxyFactory buildProxyFactory(PersistentClass persistentClass, Getter idGetter, Setter idSetter) { 91 HashSet proxyInterfaces = new HashSet (); 94 proxyInterfaces.add( HibernateProxy.class ); 95 96 Class mappedClass = persistentClass.getMappedClass(); 97 Class proxyInterface = persistentClass.getProxyInterface(); 98 99 if ( proxyInterface!=null && !mappedClass.equals( proxyInterface ) ) { 100 if ( !proxyInterface.isInterface() ) { 101 throw new MappingException( 102 "proxy must be either an interface, or the class itself: " + 103 getEntityName() 104 ); 105 } 106 proxyInterfaces.add( proxyInterface ); 107 } 108 109 if ( mappedClass.isInterface() ) { 110 proxyInterfaces.add( mappedClass ); 111 } 112 113 Iterator iter = persistentClass.getSubclassIterator(); 114 while ( iter.hasNext() ) { 115 Subclass subclass = ( Subclass ) iter.next(); 116 Class subclassProxy = subclass.getProxyInterface(); 117 Class subclassClass = subclass.getMappedClass(); 118 if ( subclassProxy!=null && !subclassClass.equals( subclassProxy ) ) { 119 if ( !proxyInterface.isInterface() ) { 120 throw new MappingException( 121 "proxy must be either an interface, or the class itself: " + 122 subclass.getEntityName() 123 ); 124 } 125 proxyInterfaces.add( subclassProxy ); 126 } 127 } 128 129 Iterator properties = persistentClass.getPropertyIterator(); 130 Class clazz = persistentClass.getMappedClass(); 131 while ( properties.hasNext() ) { 132 Property property = (Property) properties.next(); 133 Method method = property.getGetter(clazz).getMethod(); 134 if ( method != null && Modifier.isFinal( method.getModifiers() ) ) { 135 log.error("Getters of lazy classes cannot be final: " + persistentClass.getEntityName() + "." + property.getName() ); 136 } 137 method = property.getSetter(clazz).getMethod(); 138 if ( method != null && Modifier.isFinal( method.getModifiers() ) ) { 139 log.error("Setters of lazy classes cannot be final: " + persistentClass.getEntityName() + "." + property.getName() ); 140 } 141 } 142 143 Method idGetterMethod = idGetter==null ? null : idGetter.getMethod(); 144 Method idSetterMethod = idSetter==null ? null : idSetter.getMethod(); 145 146 Method proxyGetIdentifierMethod = idGetterMethod==null || proxyInterface==null ? 147 null : 148 ReflectHelper.getMethod(proxyInterface, idGetterMethod); 149 Method proxySetIdentifierMethod = idSetterMethod==null || proxyInterface==null ? 150 null : 151 ReflectHelper.getMethod(proxyInterface, idSetterMethod); 152 153 ProxyFactory pf = new CGLIBProxyFactory(); 154 try { 155 pf.postInstantiate( 156 getEntityName(), 157 mappedClass, 158 proxyInterfaces, 159 proxyGetIdentifierMethod, 160 proxySetIdentifierMethod, 161 persistentClass.hasEmbeddedIdentifier() ? 162 (AbstractComponentType) persistentClass.getIdentifier().getType() : 163 null 164 ); 165 } 166 catch ( HibernateException he ) { 167 log.warn( "could not create proxy factory for:" + getEntityName(), he ); 168 pf = null; 169 } 170 return pf; 171 } 172 173 protected Instantiator buildInstantiator(PersistentClass persistentClass) { 174 return new PojoInstantiator( persistentClass, fastClass ); 175 } 176 177 public void setPropertyValues(Object entity, Object [] values) throws HibernateException { 178 if ( !getEntityMetamodel().hasLazyProperties() && optimizer != null ) { 179 setPropertyValuesWithOptimizer( entity, values ); 180 } 181 else { 182 super.setPropertyValues( entity, values ); 183 } 184 } 185 186 public Object [] getPropertyValues(Object entity) throws HibernateException { 187 if ( shouldGetAllProperties( entity ) && optimizer != null ) { 188 return getPropertyValuesWithOptimizer( entity ); 189 } 190 else { 191 return super.getPropertyValues( entity ); 192 } 193 } 194 195 public Object [] getPropertyValuesToInsert(Object entity, Map mergeMap, SessionImplementor session) throws HibernateException { 196 if ( shouldGetAllProperties( entity ) && optimizer != null ) { 197 return getPropertyValuesWithOptimizer( entity ); 198 } 199 else { 200 return super.getPropertyValuesToInsert( entity, mergeMap, session ); 201 } 202 } 203 204 protected void setPropertyValuesWithOptimizer(Object object, Object [] values) { 205 try { 206 optimizer.setPropertyValues( object, values ); 207 } 208 catch ( Throwable t ) { 209 throw new PropertyAccessException( t, 210 ReflectHelper.PROPERTY_SET_EXCEPTION, 211 true, 212 mappedClass, 213 ReflectHelper.getPropertyName( t, optimizer ) 214 ); 215 } 216 } 217 218 protected Object [] getPropertyValuesWithOptimizer(Object object) { 219 try { 220 return optimizer.getPropertyValues( object ); 221 } 222 catch ( Throwable t ) { 223 throw new PropertyAccessException( t, 224 ReflectHelper.PROPERTY_GET_EXCEPTION, 225 false, 226 mappedClass, 227 ReflectHelper.getPropertyName( t, optimizer ) 228 ); 229 } 230 } 231 232 public EntityMode getEntityMode() { 233 return EntityMode.POJO; 234 } 235 236 public Class getMappedClass() { 237 return mappedClass; 238 } 239 240 public boolean isLifecycleImplementor() { 241 return lifecycleImplementor; 242 } 243 244 public boolean isValidatableImplementor() { 245 return validatableImplementor; 246 } 247 248 protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) { 249 return mappedProperty.getGetter( mappedEntity.getMappedClass() ); 250 } 251 252 protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) { 253 return mappedProperty.getSetter( mappedEntity.getMappedClass() ); 254 } 255 256 public Class getConcreteProxyClass() { 257 return proxyInterface; 258 } 259 260 262 public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) { 263 if ( isInstrumented() ) { 265 Set lazyProps = lazyPropertiesAreUnfetched && getEntityMetamodel().hasLazyProperties() ? 266 lazyPropertyNames : null; 267 FieldInterceptor.initFieldInterceptor( entity, getEntityName(), session, lazyProps ); 270 } 271 } 272 273 public boolean hasUninitializedLazyProperties(Object entity) { 274 if ( getEntityMetamodel().hasLazyProperties() ) { 275 FieldInterceptor callback = FieldInterceptor.getFieldInterceptor(entity); 276 return callback != null && !callback.isInitialized(); 277 } 278 else { 279 return false; 280 } 281 } 282 283 public boolean isInstrumented() { 284 return InterceptFieldEnabled.class.isAssignableFrom( getMappedClass() ); 285 } 286 287 } 288 | Popular Tags |