HHH-10280 - Remove legacy bytecode enhancement artifacts

This commit is contained in:
Steve Ebersole 2015-11-12 19:47:18 -06:00
parent c0528b7079
commit 472f4ab9ef
134 changed files with 638 additions and 6420 deletions

View File

@ -8,9 +8,7 @@ package org.hibernate;
import java.util.Iterator;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoader;
import org.hibernate.bytecode.instrumentation.internal.FieldInterceptionHelper;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.HibernateIterator;
import org.hibernate.engine.jdbc.LobCreator;
@ -174,16 +172,11 @@ public final class Hibernate {
if ( entity instanceof PersistentAttributeInterceptable ) {
PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
if ( interceptor != null && interceptor instanceof LazyAttributeLoader ) {
return ( (LazyAttributeLoader) interceptor ).isAttributeLoaded( propertyName );
if ( interceptor != null && interceptor instanceof LazyAttributeLoadingInterceptor ) {
return ( (LazyAttributeLoadingInterceptor) interceptor ).isAttributeLoaded( propertyName );
}
}
if ( FieldInterceptionHelper.isInstrumented( entity ) ) {
final FieldInterceptor interceptor = FieldInterceptionHelper.extractFieldInterceptor( entity );
return interceptor == null || interceptor.isInitialized( propertyName );
}
return true;
}

View File

@ -1,93 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.buildtime.internal;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Set;
import javassist.bytecode.ClassFile;
import org.hibernate.bytecode.buildtime.spi.AbstractInstrumenter;
import org.hibernate.bytecode.buildtime.spi.BasicClassFilter;
import org.hibernate.bytecode.buildtime.spi.ClassDescriptor;
import org.hibernate.bytecode.buildtime.spi.Logger;
import org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl;
import org.hibernate.bytecode.internal.javassist.FieldHandled;
import org.hibernate.bytecode.spi.ClassTransformer;
import org.hibernate.internal.log.DeprecationLogger;
/**
* Strategy for performing build-time instrumentation of persistent classes in order to enable
* field-level interception using Javassist.
*
* @author Steve Ebersole
* @author Muga Nishizawa
*/
public class JavassistInstrumenter extends AbstractInstrumenter {
private static final BasicClassFilter CLASS_FILTER = new BasicClassFilter();
private final BytecodeProviderImpl provider = new BytecodeProviderImpl();
/**
* Constructs the Javassist-based instrumenter.
*
* @param logger Logger to use
* @param options Instrumentation options
*/
public JavassistInstrumenter(Logger logger, Options options) {
super( logger, options );
DeprecationLogger.DEPRECATION_LOGGER.logDeprecatedBytecodeEnhancement();
}
@Override
protected ClassDescriptor getClassDescriptor(byte[] bytecode) throws IOException {
return new CustomClassDescriptor( bytecode );
}
@Override
protected ClassTransformer getClassTransformer(ClassDescriptor descriptor, Set classNames) {
if ( descriptor.isInstrumented() ) {
logger.debug( "class [" + descriptor.getName() + "] already instrumented" );
return null;
}
else {
return provider.getTransformer( CLASS_FILTER, new CustomFieldFilter( descriptor, classNames ) );
}
}
private static class CustomClassDescriptor implements ClassDescriptor {
private final byte[] bytes;
private final ClassFile classFile;
public CustomClassDescriptor(byte[] bytes) throws IOException {
this.bytes = bytes;
this.classFile = new ClassFile( new DataInputStream( new ByteArrayInputStream( bytes ) ) );
}
public String getName() {
return classFile.getName();
}
public boolean isInstrumented() {
final String[] interfaceNames = classFile.getInterfaces();
for ( String interfaceName : interfaceNames ) {
if ( FieldHandled.class.getName().equals( interfaceName ) ) {
return true;
}
}
return false;
}
public byte[] getBytes() {
return bytes;
}
}
}

View File

@ -1,11 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* Javassist support internals
*/
package org.hibernate.bytecode.buildtime.internal;

View File

@ -1,421 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.buildtime.spi;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.hibernate.bytecode.spi.ByteCodeHelper;
import org.hibernate.bytecode.spi.ClassTransformer;
/**
* Provides the basic templating of how instrumentation should occur.
*
* @author Steve Ebersole
*/
public abstract class AbstractInstrumenter implements Instrumenter {
private static final int ZIP_MAGIC = 0x504B0304;
private static final int CLASS_MAGIC = 0xCAFEBABE;
protected final Logger logger;
protected final Options options;
/**
* Creates the basic instrumentation strategy.
*
* @param logger The bridge to the environment's logging system.
* @param options User-supplied options.
*/
public AbstractInstrumenter(Logger logger, Options options) {
this.logger = logger;
this.options = options;
}
/**
* Given the bytecode of a java class, retrieve the descriptor for that class.
*
* @param byecode The class bytecode.
*
* @return The class's descriptor
*
* @throws Exception Indicates problems access the bytecode.
*/
protected abstract ClassDescriptor getClassDescriptor(byte[] byecode) throws Exception;
/**
* Create class transformer for the class.
*
* @param descriptor The descriptor of the class to be instrumented.
* @param classNames The names of all classes to be instrumented; the "pipeline" if you will.
*
* @return The transformer for the given class; may return null to indicate that transformation should
* be skipped (ala already instrumented).
*/
protected abstract ClassTransformer getClassTransformer(ClassDescriptor descriptor, Set classNames);
/**
* The main instrumentation entry point. Given a set of files, perform instrumentation on each discovered class
* file.
*
* @param files The files.
*/
public void execute(Set<File> files) {
final Set<String> classNames = new HashSet<String>();
if ( options.performExtendedInstrumentation() ) {
logger.debug( "collecting class names for extended instrumentation determination" );
try {
for ( Object file1 : files ) {
final File file = (File) file1;
collectClassNames( file, classNames );
}
}
catch ( ExecutionException ee ) {
throw ee;
}
catch ( Exception e ) {
throw new ExecutionException( e );
}
}
logger.info( "starting instrumentation" );
try {
for ( File file : files ) {
processFile( file, classNames );
}
}
catch ( ExecutionException ee ) {
throw ee;
}
catch ( Exception e ) {
throw new ExecutionException( e );
}
}
/**
* Extract the names of classes from file, adding them to the classNames collection.
* <p/>
* IMPL NOTE : file here may be either a class file or a jar. If a jar, all entries in the jar file are
* processed.
*
* @param file The file from which to extract class metadata (descriptor).
* @param classNames The collected class name collection.
*
* @throws Exception indicates problems accessing the file or its contents.
*/
private void collectClassNames(File file, final Set<String> classNames) throws Exception {
if ( isClassFile( file ) ) {
final byte[] bytes = ByteCodeHelper.readByteCode( file );
final ClassDescriptor descriptor = getClassDescriptor( bytes );
classNames.add( descriptor.getName() );
}
else if ( isJarFile( file ) ) {
final ZipEntryHandler collector = new ZipEntryHandler() {
public void handleEntry(ZipEntry entry, byte[] byteCode) throws Exception {
if ( !entry.isDirectory() ) {
// see if the entry represents a class file
final DataInputStream din = new DataInputStream( new ByteArrayInputStream( byteCode ) );
if ( din.readInt() == CLASS_MAGIC ) {
classNames.add( getClassDescriptor( byteCode ).getName() );
}
}
}
};
final ZipFileProcessor processor = new ZipFileProcessor( collector );
processor.process( file );
}
}
/**
* Does this file represent a compiled class?
*
* @param file The file to check.
*
* @return True if the file is a class; false otherwise.
*
* @throws IOException Indicates problem access the file.
*/
protected final boolean isClassFile(File file) throws IOException {
return checkMagic( file, CLASS_MAGIC );
}
/**
* Does this file represent a zip file of some format?
*
* @param file The file to check.
*
* @return True if the file is n archive; false otherwise.
*
* @throws IOException Indicates problem access the file.
*/
protected final boolean isJarFile(File file) throws IOException {
return checkMagic( file, ZIP_MAGIC );
}
protected final boolean checkMagic(File file, long magic) throws IOException {
final DataInputStream in = new DataInputStream( new FileInputStream( file ) );
try {
final int m = in.readInt();
return magic == m;
}
finally {
in.close();
}
}
/**
* Actually process the file by applying instrumentation transformations to any classes it contains.
* <p/>
* Again, just like with {@link #collectClassNames} this method can handle both class and archive files.
*
* @param file The file to process.
* @param classNames The 'pipeline' of classes to be processed. Only actually populated when the user
* specifies to perform {@link org.hibernate.bytecode.buildtime.spi.Instrumenter.Options#performExtendedInstrumentation() extended} instrumentation.
*
* @throws Exception Indicates an issue either access files or applying the transformations.
*/
protected void processFile(File file, Set<String> classNames) throws Exception {
if ( isClassFile( file ) ) {
logger.debug( "processing class file : " + file.getAbsolutePath() );
processClassFile( file, classNames );
}
else if ( isJarFile( file ) ) {
logger.debug( "processing jar file : " + file.getAbsolutePath() );
processJarFile( file, classNames );
}
else {
logger.debug( "ignoring file : " + file.getAbsolutePath() );
}
}
/**
* Process a class file. Delegated to from {@link #processFile} in the case of a class file.
*
* @param file The class file to process.
* @param classNames The 'pipeline' of classes to be processed. Only actually populated when the user
* specifies to perform {@link org.hibernate.bytecode.buildtime.spi.Instrumenter.Options#performExtendedInstrumentation() extended} instrumentation.
*
* @throws Exception Indicates an issue either access files or applying the transformations.
*/
protected void processClassFile(File file, Set<String> classNames) throws Exception {
final byte[] bytes = ByteCodeHelper.readByteCode( file );
final ClassDescriptor descriptor = getClassDescriptor( bytes );
final ClassTransformer transformer = getClassTransformer( descriptor, classNames );
if ( transformer == null ) {
logger.debug( "no trasformer for class file : " + file.getAbsolutePath() );
return;
}
logger.info( "processing class : " + descriptor.getName() + "; file = " + file.getAbsolutePath() );
final byte[] transformedBytes = transformer.transform(
getClass().getClassLoader(),
descriptor.getName(),
null,
null,
descriptor.getBytes()
);
final OutputStream out = new FileOutputStream( file );
try {
out.write( transformedBytes );
out.flush();
}
finally {
try {
out.close();
}
catch ( IOException ignore) {
// intentionally empty
}
}
}
/**
* Process an archive file. Delegated to from {@link #processFile} in the case of an archive file.
*
* @param file The archive file to process.
* @param classNames The 'pipeline' of classes to be processed. Only actually populated when the user
* specifies to perform {@link org.hibernate.bytecode.buildtime.spi.Instrumenter.Options#performExtendedInstrumentation() extended} instrumentation.
*
* @throws Exception Indicates an issue either access files or applying the transformations.
*/
protected void processJarFile(final File file, final Set<String> classNames) throws Exception {
final File tempFile = File.createTempFile(
file.getName(),
null,
new File( file.getAbsoluteFile().getParent() )
);
try {
final FileOutputStream fout = new FileOutputStream( tempFile, false );
try {
final ZipOutputStream out = new ZipOutputStream( fout );
final ZipEntryHandler transformer = new ZipEntryHandler() {
public void handleEntry(ZipEntry entry, byte[] byteCode) throws Exception {
logger.debug( "starting zip entry : " + entry.toString() );
if ( !entry.isDirectory() ) {
// see if the entry represents a class file
final DataInputStream din = new DataInputStream( new ByteArrayInputStream( byteCode ) );
if ( din.readInt() == CLASS_MAGIC ) {
final ClassDescriptor descriptor = getClassDescriptor( byteCode );
final ClassTransformer transformer = getClassTransformer( descriptor, classNames );
if ( transformer == null ) {
logger.debug( "no transformer for zip entry : " + entry.toString() );
}
else {
logger.info( "processing class : " + descriptor.getName() + "; entry = " + file.getAbsolutePath() );
byteCode = transformer.transform(
getClass().getClassLoader(),
descriptor.getName(),
null,
null,
descriptor.getBytes()
);
}
}
else {
logger.debug( "ignoring zip entry : " + entry.toString() );
}
}
final ZipEntry outEntry = new ZipEntry( entry.getName() );
outEntry.setMethod( entry.getMethod() );
outEntry.setComment( entry.getComment() );
outEntry.setSize( byteCode.length );
if ( outEntry.getMethod() == ZipEntry.STORED ){
final CRC32 crc = new CRC32();
crc.update( byteCode );
outEntry.setCrc( crc.getValue() );
outEntry.setCompressedSize( byteCode.length );
}
out.putNextEntry( outEntry );
out.write( byteCode );
out.closeEntry();
}
};
final ZipFileProcessor processor = new ZipFileProcessor( transformer );
processor.process( file );
out.close();
}
finally{
fout.close();
}
if ( file.delete() ) {
final File newFile = new File( tempFile.getAbsolutePath() );
if( ! newFile.renameTo( file ) ) {
throw new IOException( "can not rename " + tempFile + " to " + file );
}
}
else {
throw new IOException( "can not delete " + file );
}
}
finally {
if ( ! tempFile.delete() ) {
logger.info( "Unable to cleanup temporary jar file : " + tempFile.getAbsolutePath() );
}
}
}
/**
* Allows control over what exactly to transform.
*/
protected class CustomFieldFilter implements FieldFilter {
private final ClassDescriptor descriptor;
private final Set classNames;
public CustomFieldFilter(ClassDescriptor descriptor, Set classNames) {
this.descriptor = descriptor;
this.classNames = classNames;
}
public boolean shouldInstrumentField(String className, String fieldName) {
if ( descriptor.getName().equals( className ) ) {
logger.trace( "accepting transformation of field [" + className + "." + fieldName + "]" );
return true;
}
else {
logger.trace( "rejecting transformation of field [" + className + "." + fieldName + "]" );
return false;
}
}
public boolean shouldTransformFieldAccess(
String transformingClassName,
String fieldOwnerClassName,
String fieldName) {
if ( descriptor.getName().equals( fieldOwnerClassName ) ) {
logger.trace( "accepting transformation of field access [" + fieldOwnerClassName + "." + fieldName + "]" );
return true;
}
else if ( options.performExtendedInstrumentation() && classNames.contains( fieldOwnerClassName ) ) {
logger.trace( "accepting extended transformation of field access [" + fieldOwnerClassName + "." + fieldName + "]" );
return true;
}
else {
logger.trace( "rejecting transformation of field access [" + fieldOwnerClassName + "." + fieldName + "]; caller = " + transformingClassName );
return false;
}
}
}
/**
* General strategy contract for handling entries in an archive file.
*/
private static interface ZipEntryHandler {
/**
* Apply strategy to the given archive entry.
*
* @param entry The archive file entry.
* @param byteCode The bytes making up the entry
*
* @throws Exception Problem handling entry
*/
public void handleEntry(ZipEntry entry, byte[] byteCode) throws Exception;
}
/**
* Applies {@link ZipEntryHandler} strategies to the entries of an archive file.
*/
private static class ZipFileProcessor {
private final ZipEntryHandler entryHandler;
public ZipFileProcessor(ZipEntryHandler entryHandler) {
this.entryHandler = entryHandler;
}
public void process(File file) throws Exception {
final ZipInputStream zip = new ZipInputStream( new FileInputStream( file ) );
try {
ZipEntry entry;
while ( (entry = zip.getNextEntry()) != null ) {
final byte[] bytes = ByteCodeHelper.readByteCode( zip );
entryHandler.handleEntry( entry, bytes );
zip.closeEntry();
}
}
finally {
zip.close();
}
}
}
}

View File

@ -1,65 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.buildtime.spi;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* BasicClassFilter provides class filtering based on a series of packages to
* be included and/or a series of explicit class names to be included. If
* neither is specified, then no restrictions are applied.
*
* @author Steve Ebersole
*/
public class BasicClassFilter implements ClassFilter {
private final String[] includedPackages;
private final Set<String> includedClassNames = new HashSet<String>();
private final boolean isAllEmpty;
/**
* Constructs a BasicClassFilter with given configuration.
*/
public BasicClassFilter() {
this( null, null );
}
/**
* Constructs a BasicClassFilter with standard set of configuration.
*
* @param includedPackages Name of packages whose classes should be accepted.
* @param includedClassNames Name of classes that should be accepted.
*/
public BasicClassFilter(String[] includedPackages, String[] includedClassNames) {
this.includedPackages = includedPackages;
if ( includedClassNames != null ) {
this.includedClassNames.addAll( Arrays.asList( includedClassNames ) );
}
isAllEmpty = ( this.includedPackages == null || this.includedPackages.length == 0 )
&& ( this.includedClassNames.isEmpty() );
}
@Override
public boolean shouldInstrumentClass(String className) {
return isAllEmpty ||
includedClassNames.contains( className ) ||
isInIncludedPackage( className );
}
private boolean isInIncludedPackage(String className) {
if ( includedPackages != null ) {
for ( String includedPackage : includedPackages ) {
if ( className.startsWith( includedPackage ) ) {
return true;
}
}
}
return false;
}
}

View File

@ -1,36 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.buildtime.spi;
/**
* Contract describing the information Hibernate needs in terms of instrumenting
* a class, either via ant task or dynamic classloader.
*
* @author Steve Ebersole
*/
public interface ClassDescriptor {
/**
* The name of the class.
*
* @return The class name.
*/
public String getName();
/**
* Determine if the class is already instrumented.
*
* @return True if already instrumented; false otherwise.
*/
public boolean isInstrumented();
/**
* The bytes making up the class' bytecode.
*
* @return The bytecode bytes.
*/
public byte[] getBytes();
}

View File

@ -1,23 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.buildtime.spi;
/**
* Used to determine whether a class should be instrumented.
*
* @author Steve Ebersole
*/
public interface ClassFilter {
/**
* Should this class be included in instrumentation.
*
* @param className The name of the class to check
*
* @return {@literal true} to include class in instrumentation; {@literal false} otherwise.
*/
public boolean shouldInstrumentClass(String className);
}

View File

@ -1,43 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.buildtime.spi;
/**
* Indicates problem performing the instrumentation execution.
*
* @author Steve Ebersole
*/
@SuppressWarnings( {"UnusedDeclaration"})
public class ExecutionException extends RuntimeException {
/**
* Constructs an ExecutionException.
*
* @param message The message explaining the exception condition
*/
public ExecutionException(String message) {
super( message );
}
/**
* Constructs an ExecutionException.
*
* @param cause The underlying cause.
*/
public ExecutionException(Throwable cause) {
super( cause );
}
/**
* Constructs an ExecutionException.
*
* @param message The message explaining the exception condition
* @param cause The underlying cause.
*/
public ExecutionException(String message, Throwable cause) {
super( message, cause );
}
}

View File

@ -1,35 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.buildtime.spi;
/**
* Used to determine whether a field reference should be instrumented.
*
* @author Steve Ebersole
*/
public interface FieldFilter {
/**
* Should this field definition be instrumented?
*
* @param className The name of the class currently being processed
* @param fieldName The name of the field being checked.
* @return True if we should instrument this field.
*/
public boolean shouldInstrumentField(String className, String fieldName);
/**
* Should we instrument *access to* the given field. This differs from
* {@link #shouldInstrumentField} in that here we are talking about a particular usage of
* a field.
*
* @param transformingClassName The class currently being transformed.
* @param fieldOwnerClassName The name of the class owning this field being checked.
* @param fieldName The name of the field being checked.
* @return True if this access should be transformed.
*/
public boolean shouldTransformFieldAccess(String transformingClassName, String fieldOwnerClassName, String fieldName);
}

View File

@ -1,36 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.buildtime.spi;
import java.io.File;
import java.util.Set;
/**
* Basic contract for performing instrumentation.
*
* @author Steve Ebersole
*/
public interface Instrumenter {
/**
* Perform the instrumentation.
*
* @param files The file on which to perform instrumentation
*/
public void execute(Set<File> files);
/**
* Instrumentation options.
*/
public static interface Options {
/**
* Should we enhance references to class fields outside the class itself?
*
* @return {@literal true}/{@literal false}
*/
public boolean performExtendedInstrumentation();
}
}

View File

@ -1,50 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.buildtime.spi;
/**
* Provides an abstraction for how instrumentation does logging because it is usually run in environments (Ant/Maven)
* with their own logging infrastructure. This abstraction allows proper bridging.
*
* @author Steve Ebersole
*/
public interface Logger {
/**
* Log a message with TRACE semantics.
*
* @param message The message to log.
*/
public void trace(String message);
/**
* Log a message with DEBUG semantics.
*
* @param message The message to log.
*/
public void debug(String message);
/**
* Log a message with INFO semantics.
*
* @param message The message to log.
*/
public void info(String message);
/**
* Log a message with WARN semantics.
*
* @param message The message to log.
*/
public void warn(String message);
/**
* Log a message with ERROR semantics.
*
* @param message The message to log.
*/
public void error(String message);
}

View File

@ -1,13 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* Package defining build-time bytecode code enhancement (instrumentation) support.
*
* This package should mostly be considered deprecated in favor of {@link org.hibernate.bytecode.enhance}
*/
package org.hibernate.bytecode.buildtime.spi;

View File

@ -25,7 +25,7 @@ import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.bytecode.enhance.spi.EnhancementException;
import org.hibernate.bytecode.enhance.spi.Enhancer;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoader;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.SelfDirtinessTracker;
@ -315,7 +315,7 @@ public class EntityEnhancer extends Enhancer {
EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME,
EnhancerConstants.TRACKER_COLLECTION_NAME,
COLLECTION_TRACKER_IMPL,
LazyAttributeLoader.class.getName()
LazyAttributeLoadingInterceptor.class.getName()
)
);
@ -324,7 +324,7 @@ public class EntityEnhancer extends Enhancer {
String.format(
" if(%1$s != null && %1$s instanceof %2$s) lazyInterceptor = (%2$s) %1$s;%n%n",
EnhancerConstants.INTERCEPTOR_FIELD_NAME,
LazyAttributeLoader.class.getName()
LazyAttributeLoadingInterceptor.class.getName()
)
);
}

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.instrumentation.spi;
package org.hibernate.bytecode.enhance.spi;
import java.io.Serializable;

View File

@ -16,7 +16,7 @@ import org.hibernate.bytecode.enhance.internal.tracker.SimpleFieldTracker;
import org.hibernate.bytecode.enhance.spi.CollectionTracker;
import org.hibernate.bytecode.enhance.spi.interceptor.Helper.Consumer;
import org.hibernate.bytecode.enhance.spi.interceptor.Helper.LazyInitializationWork;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionImplementor;
@ -30,8 +30,8 @@ import org.jboss.logging.Logger;
*
* @author Luis Barreiro
*/
public class LazyAttributeLoader implements PersistentAttributeInterceptor, Consumer {
private static final Logger log = Logger.getLogger( LazyAttributeLoader.class );
public class LazyAttributeLoadingInterceptor implements PersistentAttributeInterceptor, Consumer {
private static final Logger log = Logger.getLogger( LazyAttributeLoadingInterceptor.class );
private transient SessionImplementor session;
@ -43,7 +43,7 @@ public class LazyAttributeLoader implements PersistentAttributeInterceptor, Cons
private final SimpleFieldTracker initializedFields = new SimpleFieldTracker();
public LazyAttributeLoader(SessionImplementor session, Set<String> lazyFields, String entityName) {
public LazyAttributeLoadingInterceptor(SessionImplementor session, Set<String> lazyFields, String entityName) {
this.session = session;
this.lazyFields = lazyFields;
this.entityName = entityName;
@ -130,7 +130,7 @@ public class LazyAttributeLoader implements PersistentAttributeInterceptor, Cons
return lazyFields == null || !lazyFields.contains( fieldName ) || initializedFields.contains( fieldName );
}
public boolean isUninitialized() {
public boolean hasAnyUninitializedAttributes() {
if ( lazyFields != null ) {
for ( String fieldName : lazyFields ) {
if ( !initializedFields.contains( fieldName ) ) {

View File

@ -1,164 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.instrumentation.internal;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.bytecode.instrumentation.internal.javassist.JavassistHelper;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.engine.spi.SessionImplementor;
/**
* Helper class for dealing with enhanced entity classes.
*
* These operations are expensive. They are only meant to be used when code does not have access to a
* SessionFactory (namely from the instrumentation tasks). When code has access to a SessionFactory,
* {@link org.hibernate.bytecode.spi.EntityInstrumentationMetadata} should be used instead to query the
* instrumentation state. EntityInstrumentationMetadata is accessed from the
* {@link org.hibernate.persister.entity.EntityPersister} via the
* {@link org.hibernate.persister.entity.EntityPersister#getInstrumentationMetadata()} method.
*
* @author Steve Ebersole
*/
public class FieldInterceptionHelper {
private static final Set<Delegate> INSTRUMENTATION_DELEGATES = buildInstrumentationDelegates();
private static Set<Delegate> buildInstrumentationDelegates() {
final HashSet<Delegate> delegates = new HashSet<Delegate>();
delegates.add( JavassistDelegate.INSTANCE );
return delegates;
}
/**
* Utility to check to see if a given entity class is instrumented.
*
* @param entityClass The entity class to check
*
* @return {@code true} if it has been instrumented; {@code false} otherwise
*/
public static boolean isInstrumented(Class entityClass) {
for ( Delegate delegate : INSTRUMENTATION_DELEGATES ) {
if ( delegate.isInstrumented( entityClass ) ) {
return true;
}
}
return false;
}
/**
* Utility to check to see if a given object is an instance of an instrumented class. If the instance
* is {@code null}, the check returns {@code false}
*
* @param object The object to check
*
* @return {@code true} if it has been instrumented; {@code false} otherwise
*/
public static boolean isInstrumented(Object object) {
return object != null && isInstrumented( object.getClass() );
}
/**
* Assuming the given object is an enhanced entity, extract and return its interceptor. Will
* return {@code null} if object is {@code null}, or if the object was deemed to not be
* instrumented
*
* @param object The object from which to extract the interceptor
*
* @return The extracted interceptor, or {@code null}
*/
public static FieldInterceptor extractFieldInterceptor(Object object) {
if ( object == null ) {
return null;
}
FieldInterceptor interceptor = null;
for ( Delegate delegate : INSTRUMENTATION_DELEGATES ) {
interceptor = delegate.extractInterceptor( object );
if ( interceptor != null ) {
break;
}
}
return interceptor;
}
/**
* Assuming the given object is an enhanced entity, inject a field interceptor.
*
* @param entity The entity instance
* @param entityName The entity name
* @param uninitializedFieldNames The names of any uninitialized fields
* @param session The session
*
* @return The injected interceptor
*/
public static FieldInterceptor injectFieldInterceptor(
Object entity,
String entityName,
Set uninitializedFieldNames,
SessionImplementor session) {
if ( entity == null ) {
return null;
}
FieldInterceptor interceptor = null;
for ( Delegate delegate : INSTRUMENTATION_DELEGATES ) {
interceptor = delegate.injectInterceptor( entity, entityName, uninitializedFieldNames, session );
if ( interceptor != null ) {
break;
}
}
return interceptor;
}
private static interface Delegate {
public boolean isInstrumented(Class classToCheck);
public FieldInterceptor extractInterceptor(Object entity);
public FieldInterceptor injectInterceptor(Object entity, String entityName, Set uninitializedFieldNames, SessionImplementor session);
}
private static class JavassistDelegate implements Delegate {
public static final JavassistDelegate INSTANCE = new JavassistDelegate();
public static final String MARKER = "org.hibernate.bytecode.internal.javassist.FieldHandled";
@Override
public boolean isInstrumented(Class classToCheck) {
for ( Class definedInterface : classToCheck.getInterfaces() ) {
if ( MARKER.equals( definedInterface.getName() ) ) {
return true;
}
}
return false;
}
@Override
public FieldInterceptor extractInterceptor(Object entity) {
for ( Class definedInterface : entity.getClass().getInterfaces() ) {
if ( MARKER.equals( definedInterface.getName() ) ) {
return JavassistHelper.extractFieldInterceptor( entity );
}
}
return null;
}
@Override
public FieldInterceptor injectInterceptor(
Object entity,
String entityName,
Set uninitializedFieldNames,
SessionImplementor session) {
for ( Class definedInterface : entity.getClass().getInterfaces() ) {
if ( MARKER.equals( definedInterface.getName() ) ) {
return JavassistHelper.injectFieldInterceptor( entity, entityName, uninitializedFieldNames, session );
}
}
return null;
}
}
private FieldInterceptionHelper() {
}
}

View File

@ -1,145 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.instrumentation.internal.javassist;
import java.io.Serializable;
import java.util.Set;
import org.hibernate.bytecode.instrumentation.spi.AbstractFieldInterceptor;
import org.hibernate.bytecode.internal.javassist.FieldHandler;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
/**
* A field-level interceptor that initializes lazily fetched properties.
* This interceptor can be attached to classes instrumented by Javassist.
* Note that this implementation assumes that the instance variable
* name is the same as the name of the persistent property that must
* be loaded.
* </p>
* Note: most of the interesting functionality here is farmed off
* to the super-class. The stuff here mainly acts as an adapter to the
* Javassist-specific functionality, routing interception through
* the super-class's intercept() method
*
* @author Steve Ebersole
*/
final class FieldInterceptorImpl extends AbstractFieldInterceptor implements FieldHandler, Serializable {
FieldInterceptorImpl(SessionImplementor session, Set uninitializedFields, String entityName) {
super( session, uninitializedFields, entityName );
}
// FieldHandler impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean readBoolean(Object target, String name, boolean oldValue) {
return (Boolean) intercept( target, name, oldValue );
}
@Override
public byte readByte(Object target, String name, byte oldValue) {
return (Byte) intercept( target, name, oldValue );
}
@Override
public char readChar(Object target, String name, char oldValue) {
return (Character) intercept( target, name, oldValue );
}
@Override
public double readDouble(Object target, String name, double oldValue) {
return (Double) intercept( target, name, oldValue );
}
@Override
public float readFloat(Object target, String name, float oldValue) {
return (Float) intercept( target, name, oldValue );
}
@Override
public int readInt(Object target, String name, int oldValue) {
return (Integer) intercept( target, name, oldValue );
}
@Override
public long readLong(Object target, String name, long oldValue) {
return (Long) intercept( target, name, oldValue );
}
@Override
public short readShort(Object target, String name, short oldValue) {
return (Short) intercept( target, name, oldValue );
}
@Override
public Object readObject(Object target, String name, Object oldValue) {
Object value = intercept( target, name, oldValue );
if ( value instanceof HibernateProxy ) {
final LazyInitializer li = ( (HibernateProxy) value ).getHibernateLazyInitializer();
if ( li.isUnwrap() ) {
value = li.getImplementation();
}
}
return value;
}
@Override
public boolean writeBoolean(Object target, String name, boolean oldValue, boolean newValue) {
dirty();
intercept( target, name, oldValue );
return newValue;
}
@Override
public byte writeByte(Object target, String name, byte oldValue, byte newValue) {
dirty();
intercept( target, name, oldValue );
return newValue;
}
@Override
public char writeChar(Object target, String name, char oldValue, char newValue) {
dirty();
intercept( target, name, oldValue );
return newValue;
}
@Override
public double writeDouble(Object target, String name, double oldValue, double newValue) {
dirty();
intercept( target, name, oldValue );
return newValue;
}
@Override
public float writeFloat(Object target, String name, float oldValue, float newValue) {
dirty();
intercept( target, name, oldValue );
return newValue;
}
@Override
public int writeInt(Object target, String name, int oldValue, int newValue) {
dirty();
intercept( target, name, oldValue );
return newValue;
}
@Override
public long writeLong(Object target, String name, long oldValue, long newValue) {
dirty();
intercept( target, name, oldValue );
return newValue;
}
@Override
public short writeShort(Object target, String name, short oldValue, short newValue) {
dirty();
intercept( target, name, oldValue );
return newValue;
}
@Override
public Object writeObject(Object target, String name, Object oldValue, Object newValue) {
dirty();
intercept( target, name, oldValue );
return newValue;
}
@Override
public String toString() {
return "FieldInterceptorImpl(entityName=" + getEntityName() +
",dirty=" + isDirty() +
",uninitializedFields=" + getUninitializedFields() +
')';
}
}

View File

@ -1,54 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.instrumentation.internal.javassist;
import java.util.Set;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.bytecode.internal.javassist.FieldHandled;
import org.hibernate.engine.spi.SessionImplementor;
/**
* Javassist specific helper
*
* @author Steve Ebersole
*/
public class JavassistHelper {
private JavassistHelper() {
}
/**
* Perform the Javassist-specific field interceptor extraction
*
* @param entity The entity from which to extract the interceptor
*
* @return The extracted interceptor
*/
public static FieldInterceptor extractFieldInterceptor(Object entity) {
return (FieldInterceptor) ( (FieldHandled) entity ).getFieldHandler();
}
/**
* Perform the Javassist-specific field interceptor injection
*
* @param entity The entity instance
* @param entityName The entity name
* @param uninitializedFieldNames The names of any uninitialized fields
* @param session The session
*
* @return The generated and injected interceptor
*/
public static FieldInterceptor injectFieldInterceptor(
Object entity,
String entityName,
Set uninitializedFieldNames,
SessionImplementor session) {
final FieldInterceptorImpl fieldInterceptor = new FieldInterceptorImpl( session, uninitializedFieldNames, entityName );
( (FieldHandled) entity ).setFieldHandler( fieldInterceptor );
return fieldInterceptor;
}
}

View File

@ -1,11 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* Javassist support internals
*/
package org.hibernate.bytecode.instrumentation.internal.javassist;

View File

@ -1,11 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* Bytecode instrumentation internals
*/
package org.hibernate.bytecode.instrumentation.internal;

View File

@ -1,15 +0,0 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<html>
<head></head>
<body>
<p>
This package implements an interception mechanism for lazy property fetching, based on bytecode instrumentation.
</p>
</body>
</html>

View File

@ -1,145 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.instrumentation.spi;
import java.io.Serializable;
import java.util.Set;
import org.hibernate.LazyInitializationException;
import org.hibernate.engine.spi.SessionImplementor;
/**
* Base support for FieldInterceptor implementations.
*
* @author Steve Ebersole
*/
public abstract class AbstractFieldInterceptor implements FieldInterceptor, Serializable {
private transient SessionImplementor session;
private Set uninitializedFields;
private final String entityName;
private transient boolean initializing;
private boolean dirty;
protected AbstractFieldInterceptor(SessionImplementor session, Set uninitializedFields, String entityName) {
this.session = session;
this.uninitializedFields = uninitializedFields;
this.entityName = entityName;
}
// FieldInterceptor impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public final void setSession(SessionImplementor session) {
this.session = session;
}
@Override
public final boolean isInitialized() {
return uninitializedFields == null || uninitializedFields.size() == 0;
}
@Override
public final boolean isInitialized(String field) {
return uninitializedFields == null || !uninitializedFields.contains( field );
}
@Override
public final void dirty() {
dirty = true;
}
@Override
public final boolean isDirty() {
return dirty;
}
@Override
public final void clearDirty() {
dirty = false;
}
// subclass accesses ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Interception of access to the named field
*
* @param target The call target
* @param fieldName The name of the field.
* @param value The value.
*
* @return ?
*/
protected final Object intercept(Object target, String fieldName, Object value) {
if ( initializing ) {
return value;
}
if ( uninitializedFields != null && uninitializedFields.contains( fieldName ) ) {
if ( session == null ) {
throw new LazyInitializationException( "entity with lazy properties is not associated with a session" );
}
else if ( !session.isOpen() || !session.isConnected() ) {
throw new LazyInitializationException( "session is not connected" );
}
final Object result;
initializing = true;
try {
result = ( (LazyPropertyInitializer) session.getFactory().getEntityPersister( entityName ) )
.initializeLazyProperty( fieldName, target, session );
}
finally {
initializing = false;
}
// let's assume that there is only one lazy fetch group, for now!
uninitializedFields = null;
return result;
}
else {
return value;
}
}
/**
* Access to the session
*
* @return The associated session
*/
public final SessionImplementor getSession() {
return session;
}
/**
* Access to all currently uninitialized fields
*
* @return The name of all currently uninitialized fields
*/
public final Set getUninitializedFields() {
return uninitializedFields;
}
/**
* Access to the intercepted entity name
*
* @return The entity name
*/
public final String getEntityName() {
return entityName;
}
/**
* Is the instance currently initializing?
*
* @return true/false.
*/
public final boolean isInitializing() {
return initializing;
}
}

View File

@ -1,56 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.instrumentation.spi;
import org.hibernate.engine.spi.SessionImplementor;
/**
* Contract for field interception handlers.
*
* @author Steve Ebersole
*/
public interface FieldInterceptor {
/**
* Use to associate the entity to which we are bound to the given session.
*
* @param session The session to which we are now associated.
*/
public void setSession(SessionImplementor session);
/**
* Is the entity to which we are bound completely initialized?
*
* @return True if the entity is initialized; otherwise false.
*/
public boolean isInitialized();
/**
* The the given field initialized for the entity to which we are bound?
*
* @param field The name of the field to check
* @return True if the given field is initialized; otherwise false.
*/
public boolean isInitialized(String field);
/**
* Forcefully mark the entity as being dirty.
*/
public void dirty();
/**
* Is the entity considered dirty?
*
* @return True if the entity is dirty; otherwise false.
*/
public boolean isDirty();
/**
* Clear the internal dirty flag.
*/
public void clearDirty();
}

View File

@ -1,13 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* Package defining bytecode code enhancement (instrumentation) support.
*
* This package should mostly be considered deprecated in favor of {@link org.hibernate.bytecode.enhance}
*/
package org.hibernate.bytecode.instrumentation.spi;

View File

@ -7,19 +7,10 @@
package org.hibernate.bytecode.internal.javassist;
import java.lang.reflect.Modifier;
import java.util.Set;
import org.hibernate.bytecode.buildtime.spi.ClassFilter;
import org.hibernate.bytecode.buildtime.spi.FieldFilter;
import org.hibernate.bytecode.instrumentation.internal.javassist.JavassistHelper;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.bytecode.spi.BytecodeProvider;
import org.hibernate.bytecode.spi.ClassTransformer;
import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
import org.hibernate.bytecode.spi.NotInstrumentedException;
import org.hibernate.bytecode.spi.ProxyFactoryFactory;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
@ -101,71 +92,4 @@ public class BytecodeProviderImpl implements BytecodeProvider {
return null;
}
@Override
public ClassTransformer getTransformer(ClassFilter classFilter, FieldFilter fieldFilter) {
return new JavassistClassTransformer( classFilter, fieldFilter );
}
@Override
public EntityInstrumentationMetadata getEntityInstrumentationMetadata(Class entityClass) {
return new EntityInstrumentationMetadataImpl( entityClass );
}
private static class EntityInstrumentationMetadataImpl implements EntityInstrumentationMetadata {
private final Class entityClass;
private final boolean isInstrumented;
private EntityInstrumentationMetadataImpl(Class entityClass) {
this.entityClass = entityClass;
this.isInstrumented = FieldHandled.class.isAssignableFrom( entityClass );
}
@Override
public String getEntityName() {
return entityClass.getName();
}
@Override
public boolean isInstrumented() {
return isInstrumented;
}
@Override
public FieldInterceptor extractInterceptor(Object entity) throws NotInstrumentedException {
if ( !entityClass.isInstance( entity ) ) {
throw new IllegalArgumentException(
String.format(
"Passed entity instance [%s] is not of expected type [%s]",
entity,
getEntityName()
)
);
}
if ( ! isInstrumented() ) {
throw new NotInstrumentedException( String.format( "Entity class [%s] is not instrumented", getEntityName() ) );
}
return JavassistHelper.extractFieldInterceptor( entity );
}
@Override
public FieldInterceptor injectInterceptor(
Object entity,
String entityName,
Set uninitializedFieldNames,
SessionImplementor session) throws NotInstrumentedException {
if ( !entityClass.isInstance( entity ) ) {
throw new IllegalArgumentException(
String.format(
"Passed entity instance [%s] is not of expected type [%s]",
entity,
getEntityName()
)
);
}
if ( ! isInstrumented() ) {
throw new NotInstrumentedException( String.format( "Entity class [%s] is not instrumented", getEntityName() ) );
}
return JavassistHelper.injectFieldInterceptor( entity, entityName, uninitializedFieldNames, session );
}
}
}

View File

@ -1,59 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.internal.javassist;
/**
* Contract for deciding whether fields should be read and/or write intercepted.
*
* @author Muga Nishizawa
* @author Steve Ebersole
*/
public interface FieldFilter {
/**
* Should the given field be read intercepted?
*
* @param desc The field descriptor
* @param name The field name
*
* @return true if the given field should be read intercepted; otherwise
* false.
*/
boolean handleRead(String desc, String name);
/**
* Should the given field be write intercepted?
*
* @param desc The field descriptor
* @param name The field name
*
* @return true if the given field should be write intercepted; otherwise
* false.
*/
boolean handleWrite(String desc, String name);
/**
* Should read access to the given field be intercepted?
*
* @param fieldOwnerClassName The class where the field being accessed is defined
* @param fieldName The name of the field being accessed
*
* @return true if the given field read access should be write intercepted; otherwise
* false.
*/
boolean handleReadAccess(String fieldOwnerClassName, String fieldName);
/**
* Should write access to the given field be intercepted?
*
* @param fieldOwnerClassName The class where the field being accessed is defined
* @param fieldName The name of the field being accessed
*
* @return true if the given field write access should be write intercepted; otherwise
* false.
*/
boolean handleWriteAccess(String fieldOwnerClassName, String fieldName);
}

View File

@ -1,29 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.internal.javassist;
/**
* Interface introduced to the enhanced class in order to be able to
* inject a {@link FieldHandler} to define the interception behavior.
*
* @author Muga Nishizawa
*/
public interface FieldHandled {
/**
* Inject the field interception handler to be used.
*
* @param handler The field interception handler.
*/
public void setFieldHandler(FieldHandler handler);
/**
* Access to the current field interception handler.
*
* @return The current field interception handler.
*/
public FieldHandler getFieldHandler();
}

View File

@ -1,224 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.internal.javassist;
/**
* The interface defining how interception of a field should be handled.
*
* @author Muga Nishizawa
*/
@SuppressWarnings("UnusedDeclaration")
public interface FieldHandler {
/**
* Called to handle writing an int value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
* @param newValue The new field value.
*
* @return The new value, typically the same as the newValue argument
*/
int writeInt(Object obj, String name, int oldValue, int newValue);
/**
* Called to handle writing a char value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
* @param newValue The new field value.
*
* @return The new value, typically the same as the newValue argument
*/
char writeChar(Object obj, String name, char oldValue, char newValue);
/**
* Called to handle writing a byte value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
* @param newValue The new field value.
*
* @return The new value, typically the same as the newValue argument
*/
byte writeByte(Object obj, String name, byte oldValue, byte newValue);
/**
* Called to handle writing a boolean value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
* @param newValue The new field value.
*
* @return The new value, typically the same as the newValue argument
*/
boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue);
/**
* Called to handle writing a short value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
* @param newValue The new field value.
*
* @return The new value, typically the same as the newValue argument
*/
short writeShort(Object obj, String name, short oldValue, short newValue);
/**
* Called to handle writing a float value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
* @param newValue The new field value.
*
* @return The new value, typically the same as the newValue argument
*/
float writeFloat(Object obj, String name, float oldValue, float newValue);
/**
* Called to handle writing a double value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
* @param newValue The new field value.
*
* @return The new value, typically the same as the newValue argument
*/
double writeDouble(Object obj, String name, double oldValue, double newValue);
/**
* Called to handle writing a long value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
* @param newValue The new field value.
*
* @return The new value, typically the same as the newValue argument
*/
long writeLong(Object obj, String name, long oldValue, long newValue);
/**
* Called to handle writing an Object value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
* @param newValue The new field value.
*
* @return The new value, typically the same as the newValue argument; may be different for entity references
*/
Object writeObject(Object obj, String name, Object oldValue, Object newValue);
/**
* Called to handle reading an int value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
*
* @return The field value
*/
int readInt(Object obj, String name, int oldValue);
/**
* Called to handle reading a char value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
*
* @return The field value
*/
char readChar(Object obj, String name, char oldValue);
/**
* Called to handle reading a byte value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
*
* @return The field value
*/
byte readByte(Object obj, String name, byte oldValue);
/**
* Called to handle reading a boolean value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
*
* @return The field value
*/
boolean readBoolean(Object obj, String name, boolean oldValue);
/**
* Called to handle reading a short value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
*
* @return The field value
*/
short readShort(Object obj, String name, short oldValue);
/**
* Called to handle reading a float value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
*
* @return The field value
*/
float readFloat(Object obj, String name, float oldValue);
/**
* Called to handle reading a double value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
*
* @return The field value
*/
double readDouble(Object obj, String name, double oldValue);
/**
* Called to handle reading a long value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
*
* @return The field value
*/
long readLong(Object obj, String name, long oldValue);
/**
* Called to handle reading an Object value to a given field.
*
* @param obj The object instance on which the write was invoked
* @param name The name of the field being written
* @param oldValue The old field value
*
* @return The field value
*/
Object readObject(Object obj, String name, Object oldValue);
}

View File

@ -1,734 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.internal.javassist;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.bytecode.AccessFlag;
import javassist.bytecode.BadBytecode;
import javassist.bytecode.Bytecode;
import javassist.bytecode.ClassFile;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.CodeIterator;
import javassist.bytecode.ConstPool;
import javassist.bytecode.Descriptor;
import javassist.bytecode.FieldInfo;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.Opcode;
import javassist.bytecode.StackMapTable;
import javassist.bytecode.stackmap.MapMaker;
/**
* The thing that handles actual class enhancement in regards to
* intercepting field accesses.
*
* @author Muga Nishizawa
* @author Steve Ebersole
* @author Dustin Schultz
*/
public class FieldTransformer {
private static final String EACH_READ_METHOD_PREFIX = "$javassist_read_";
private static final String EACH_WRITE_METHOD_PREFIX = "$javassist_write_";
private static final String FIELD_HANDLED_TYPE_NAME = FieldHandled.class.getName();
private static final String HANDLER_FIELD_NAME = "$JAVASSIST_READ_WRITE_HANDLER";
private static final String FIELD_HANDLER_TYPE_NAME = FieldHandler.class.getName();
private static final String HANDLER_FIELD_DESCRIPTOR = 'L' + FIELD_HANDLER_TYPE_NAME.replace( '.', '/' ) + ';';
private static final String GETFIELDHANDLER_METHOD_NAME = "getFieldHandler";
private static final String SETFIELDHANDLER_METHOD_NAME = "setFieldHandler";
private static final String GETFIELDHANDLER_METHOD_DESCRIPTOR = "()" + HANDLER_FIELD_DESCRIPTOR;
private static final String SETFIELDHANDLER_METHOD_DESCRIPTOR = "(" + HANDLER_FIELD_DESCRIPTOR + ")V";
private final FieldFilter filter;
private final ClassPool classPool;
FieldTransformer(FieldFilter f, ClassPool c) {
filter = f;
classPool = c;
}
/**
* Transform the class contained in the given file, writing the result back to the same file.
*
* @param file The file containing the class to be transformed
*
* @throws Exception Indicates a problem performing the transformation
*/
public void transform(File file) throws Exception {
final DataInputStream in = new DataInputStream( new FileInputStream( file ) );
final ClassFile classfile = new ClassFile( in );
transform( classfile );
final DataOutputStream out = new DataOutputStream( new FileOutputStream( file ) );
try {
classfile.write( out );
}
finally {
out.close();
}
}
/**
* Transform the class defined by the given ClassFile descriptor. The ClassFile descriptor itself is mutated
*
* @param classFile The class file descriptor
*
* @throws Exception Indicates a problem performing the transformation
*/
public void transform(ClassFile classFile) throws Exception {
if ( classFile.isInterface() ) {
return;
}
try {
addFieldHandlerField( classFile );
addGetFieldHandlerMethod( classFile );
addSetFieldHandlerMethod( classFile );
addFieldHandledInterface( classFile );
addReadWriteMethods( classFile );
transformInvokevirtualsIntoPutAndGetfields( classFile );
}
catch (CannotCompileException e) {
throw new RuntimeException( e.getMessage(), e );
}
}
private void addFieldHandlerField(ClassFile classfile) throws CannotCompileException {
final ConstPool constPool = classfile.getConstPool();
final FieldInfo fieldInfo = new FieldInfo( constPool, HANDLER_FIELD_NAME, HANDLER_FIELD_DESCRIPTOR );
fieldInfo.setAccessFlags( AccessFlag.PRIVATE | AccessFlag.TRANSIENT );
classfile.addField( fieldInfo );
}
private void addGetFieldHandlerMethod(ClassFile classfile) throws CannotCompileException, BadBytecode {
final ConstPool constPool = classfile.getConstPool();
final int thisClassInfo = constPool.getThisClassInfo();
final MethodInfo getterMethodInfo = new MethodInfo(
constPool,
GETFIELDHANDLER_METHOD_NAME,
GETFIELDHANDLER_METHOD_DESCRIPTOR
);
/* local variable | this | */
final Bytecode code = new Bytecode( constPool, 2, 1 );
// aload_0 // load this
code.addAload( 0 );
// getfield // get field "$JAVASSIST_CALLBACK" defined already
code.addOpcode( Opcode.GETFIELD );
final int fieldIndex = constPool.addFieldrefInfo( thisClassInfo, HANDLER_FIELD_NAME, HANDLER_FIELD_DESCRIPTOR );
code.addIndex( fieldIndex );
// areturn // return the value of the field
code.addOpcode( Opcode.ARETURN );
getterMethodInfo.setCodeAttribute( code.toCodeAttribute() );
getterMethodInfo.setAccessFlags( AccessFlag.PUBLIC );
final CodeAttribute codeAttribute = getterMethodInfo.getCodeAttribute();
if ( codeAttribute != null ) {
final StackMapTable smt = MapMaker.make( classPool, getterMethodInfo );
codeAttribute.setAttribute( smt );
}
classfile.addMethod( getterMethodInfo );
}
private void addSetFieldHandlerMethod(ClassFile classfile) throws CannotCompileException, BadBytecode {
final ConstPool constPool = classfile.getConstPool();
final int thisClassInfo = constPool.getThisClassInfo();
final MethodInfo methodInfo = new MethodInfo(
constPool,
SETFIELDHANDLER_METHOD_NAME,
SETFIELDHANDLER_METHOD_DESCRIPTOR
);
/* local variables | this | callback | */
final Bytecode code = new Bytecode(constPool, 3, 3);
// aload_0 : load this
code.addAload( 0 );
// aload_1 : load callback
code.addAload( 1 );
// putfield // put field "$JAVASSIST_CALLBACK" defined already
code.addOpcode( Opcode.PUTFIELD );
final int fieldIndex = constPool.addFieldrefInfo( thisClassInfo, HANDLER_FIELD_NAME, HANDLER_FIELD_DESCRIPTOR );
code.addIndex( fieldIndex );
// return
code.addOpcode( Opcode.RETURN );
methodInfo.setCodeAttribute( code.toCodeAttribute() );
methodInfo.setAccessFlags( AccessFlag.PUBLIC );
final CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
if ( codeAttribute != null ) {
final StackMapTable smt = MapMaker.make( classPool, methodInfo );
codeAttribute.setAttribute( smt );
}
classfile.addMethod( methodInfo );
}
private void addFieldHandledInterface(ClassFile classfile) {
final String[] interfaceNames = classfile.getInterfaces();
final String[] newInterfaceNames = new String[interfaceNames.length + 1];
System.arraycopy( interfaceNames, 0, newInterfaceNames, 0, interfaceNames.length );
newInterfaceNames[newInterfaceNames.length - 1] = FIELD_HANDLED_TYPE_NAME;
classfile.setInterfaces( newInterfaceNames );
}
private void addReadWriteMethods(ClassFile classfile) throws CannotCompileException, BadBytecode {
final List fields = classfile.getFields();
for ( Object field : fields ) {
final FieldInfo finfo = (FieldInfo) field;
if ( (finfo.getAccessFlags() & AccessFlag.STATIC) == 0 && (!finfo.getName().equals( HANDLER_FIELD_NAME )) ) {
// case of non-static field
if ( filter.handleRead( finfo.getDescriptor(), finfo.getName() ) ) {
addReadMethod( classfile, finfo );
}
if ( filter.handleWrite( finfo.getDescriptor(), finfo.getName() ) ) {
addWriteMethod( classfile, finfo );
}
}
}
}
private void addReadMethod(ClassFile classfile, FieldInfo finfo) throws CannotCompileException, BadBytecode {
final ConstPool constPool = classfile.getConstPool();
final int thisClassInfo = constPool.getThisClassInfo();
final String readMethodDescriptor = "()" + finfo.getDescriptor();
final MethodInfo readMethodInfo = new MethodInfo(
constPool,
EACH_READ_METHOD_PREFIX + finfo.getName(),
readMethodDescriptor
);
/* local variables | target obj | each oldvalue | */
final Bytecode code = new Bytecode(constPool, 5, 3);
// aload_0
code.addAload( 0 );
// getfield // get each field
code.addOpcode( Opcode.GETFIELD );
final int baseFieldIndex = constPool.addFieldrefInfo( thisClassInfo, finfo.getName(), finfo.getDescriptor() );
code.addIndex( baseFieldIndex );
// aload_0
code.addAload( 0 );
// invokeinterface : invoke Enabled.getInterceptFieldCallback()
final int enabledClassIndex = constPool.addClassInfo( FIELD_HANDLED_TYPE_NAME );
code.addInvokeinterface(
enabledClassIndex,
GETFIELDHANDLER_METHOD_NAME,
GETFIELDHANDLER_METHOD_DESCRIPTOR,
1
);
// ifnonnull
code.addOpcode( Opcode.IFNONNULL );
code.addIndex( 4 );
// *return // each type
addTypeDependDataReturn( code, finfo.getDescriptor() );
// *store_1 // each type
addTypeDependDataStore( code, finfo.getDescriptor(), 1 );
// aload_0
code.addAload( 0 );
// invokeinterface // invoke Enabled.getInterceptFieldCallback()
code.addInvokeinterface(
enabledClassIndex,
GETFIELDHANDLER_METHOD_NAME, GETFIELDHANDLER_METHOD_DESCRIPTOR,
1
);
// aload_0
code.addAload( 0 );
// ldc // name of the field
code.addLdc( finfo.getName() );
// *load_1 // each type
addTypeDependDataLoad( code, finfo.getDescriptor(), 1 );
// invokeinterface // invoke Callback.read*() // each type
addInvokeFieldHandlerMethod(
classfile, code, finfo.getDescriptor(),
true
);
// *return // each type
addTypeDependDataReturn( code, finfo.getDescriptor() );
readMethodInfo.setCodeAttribute( code.toCodeAttribute() );
readMethodInfo.setAccessFlags( AccessFlag.PUBLIC );
final CodeAttribute codeAttribute = readMethodInfo.getCodeAttribute();
if ( codeAttribute != null ) {
final StackMapTable smt = MapMaker.make( classPool, readMethodInfo );
codeAttribute.setAttribute( smt );
}
classfile.addMethod( readMethodInfo );
}
private void addWriteMethod(ClassFile classfile, FieldInfo finfo) throws CannotCompileException, BadBytecode {
final ConstPool constPool = classfile.getConstPool();
final int thisClassInfo = constPool.getThisClassInfo();
final String writeMethodDescriptor = "(" + finfo.getDescriptor() + ")V";
final MethodInfo writeMethodInfo = new MethodInfo(
constPool,
EACH_WRITE_METHOD_PREFIX+ finfo.getName(),
writeMethodDescriptor
);
/* local variables | target obj | each oldvalue | */
final Bytecode code = new Bytecode(constPool, 6, 3);
// aload_0
code.addAload( 0 );
// invokeinterface : enabled.getInterceptFieldCallback()
final int enabledClassIndex = constPool.addClassInfo( FIELD_HANDLED_TYPE_NAME );
code.addInvokeinterface(
enabledClassIndex,
GETFIELDHANDLER_METHOD_NAME, GETFIELDHANDLER_METHOD_DESCRIPTOR,
1
);
// ifnonnull (label1)
code.addOpcode( Opcode.IFNONNULL );
code.addIndex( 9 );
// aload_0
code.addAload( 0 );
// *load_1
addTypeDependDataLoad( code, finfo.getDescriptor(), 1 );
// putfield
code.addOpcode( Opcode.PUTFIELD );
final int baseFieldIndex = constPool.addFieldrefInfo( thisClassInfo, finfo.getName(), finfo.getDescriptor() );
code.addIndex( baseFieldIndex );
code.growStack( -Descriptor.dataSize( finfo.getDescriptor() ) );
// return ;
code.addOpcode( Opcode.RETURN );
// aload_0
code.addAload( 0 );
// dup
code.addOpcode( Opcode.DUP );
// invokeinterface // enabled.getInterceptFieldCallback()
code.addInvokeinterface(
enabledClassIndex,
GETFIELDHANDLER_METHOD_NAME,
GETFIELDHANDLER_METHOD_DESCRIPTOR,
1
);
// aload_0
code.addAload( 0 );
// ldc // field name
code.addLdc( finfo.getName() );
// aload_0
code.addAload( 0 );
// getfield // old value of the field
code.addOpcode( Opcode.GETFIELD );
code.addIndex( baseFieldIndex );
code.growStack( Descriptor.dataSize( finfo.getDescriptor() ) - 1 );
// *load_1
addTypeDependDataLoad( code, finfo.getDescriptor(), 1 );
// invokeinterface // callback.write*(..)
addInvokeFieldHandlerMethod( classfile, code, finfo.getDescriptor(), false );
// putfield // new value of the field
code.addOpcode( Opcode.PUTFIELD );
code.addIndex( baseFieldIndex );
code.growStack( -Descriptor.dataSize( finfo.getDescriptor() ) );
// return
code.addOpcode( Opcode.RETURN );
writeMethodInfo.setCodeAttribute( code.toCodeAttribute() );
writeMethodInfo.setAccessFlags( AccessFlag.PUBLIC );
final CodeAttribute codeAttribute = writeMethodInfo.getCodeAttribute();
if ( codeAttribute != null ) {
final StackMapTable smt = MapMaker.make( classPool, writeMethodInfo );
codeAttribute.setAttribute( smt );
}
classfile.addMethod( writeMethodInfo );
}
private void transformInvokevirtualsIntoPutAndGetfields(ClassFile classfile) throws CannotCompileException, BadBytecode {
for ( Object o : classfile.getMethods() ) {
final MethodInfo methodInfo = (MethodInfo) o;
final String methodName = methodInfo.getName();
if ( methodName.startsWith( EACH_READ_METHOD_PREFIX )
|| methodName.startsWith( EACH_WRITE_METHOD_PREFIX )
|| methodName.equals( GETFIELDHANDLER_METHOD_NAME )
|| methodName.equals( SETFIELDHANDLER_METHOD_NAME ) ) {
continue;
}
final CodeAttribute codeAttr = methodInfo.getCodeAttribute();
if ( codeAttr == null ) {
continue;
}
final CodeIterator iter = codeAttr.iterator();
while ( iter.hasNext() ) {
int pos = iter.next();
pos = transformInvokevirtualsIntoGetfields( classfile, iter, pos );
transformInvokevirtualsIntoPutfields( classfile, iter, pos );
}
final StackMapTable smt = MapMaker.make( classPool, methodInfo );
codeAttr.setAttribute( smt );
}
}
private int transformInvokevirtualsIntoGetfields(ClassFile classfile, CodeIterator iter, int pos) {
final ConstPool constPool = classfile.getConstPool();
final int c = iter.byteAt( pos );
if ( c != Opcode.GETFIELD ) {
return pos;
}
final int index = iter.u16bitAt( pos + 1 );
final String fieldName = constPool.getFieldrefName( index );
final String className = constPool.getFieldrefClassName( index );
if ( !filter.handleReadAccess( className, fieldName ) ) {
return pos;
}
final String fieldReaderMethodDescriptor = "()" + constPool.getFieldrefType( index );
final int fieldReaderMethodIndex = constPool.addMethodrefInfo(
constPool.getThisClassInfo(),
EACH_READ_METHOD_PREFIX + fieldName,
fieldReaderMethodDescriptor
);
iter.writeByte( Opcode.INVOKEVIRTUAL, pos );
iter.write16bit( fieldReaderMethodIndex, pos + 1 );
return pos;
}
private int transformInvokevirtualsIntoPutfields(ClassFile classfile, CodeIterator iter, int pos) {
final ConstPool constPool = classfile.getConstPool();
final int c = iter.byteAt( pos );
if ( c != Opcode.PUTFIELD ) {
return pos;
}
final int index = iter.u16bitAt( pos + 1 );
final String fieldName = constPool.getFieldrefName( index );
final String className = constPool.getFieldrefClassName( index );
if ( !filter.handleWriteAccess( className, fieldName ) ) {
return pos;
}
final String fieldWriterMethodDescriptor = "(" + constPool.getFieldrefType( index ) + ")V";
final int fieldWriterMethodIndex = constPool.addMethodrefInfo(
constPool.getThisClassInfo(),
EACH_WRITE_METHOD_PREFIX + fieldName,
fieldWriterMethodDescriptor
);
iter.writeByte( Opcode.INVOKEVIRTUAL, pos );
iter.write16bit( fieldWriterMethodIndex, pos + 1 );
return pos;
}
private static void addInvokeFieldHandlerMethod(
ClassFile classfile,
Bytecode code,
String typeName,
boolean isReadMethod) {
final ConstPool constPool = classfile.getConstPool();
// invokeinterface
final int callbackTypeIndex = constPool.addClassInfo( FIELD_HANDLER_TYPE_NAME );
if ( ( typeName.charAt( 0 ) == 'L' )
&& ( typeName.charAt( typeName.length() - 1 ) == ';' )
|| ( typeName.charAt( 0 ) == '[' ) ) {
// reference type
final int indexOfL = typeName.indexOf( 'L' );
String type;
if ( indexOfL == 0 ) {
// not array
type = typeName.substring( 1, typeName.length() - 1 );
type = type.replace( '/', '.' );
}
else if ( indexOfL == -1 ) {
// array of primitive type
// do nothing
type = typeName;
}
else {
// array of reference type
type = typeName.replace( '/', '.' );
}
if ( isReadMethod ) {
code.addInvokeinterface(
callbackTypeIndex,
"readObject",
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;",
4
);
// checkcast
code.addCheckcast( type );
}
else {
code.addInvokeinterface(
callbackTypeIndex,
"writeObject",
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
5
);
// checkcast
code.addCheckcast( type );
}
}
else if ( typeName.equals( "Z" ) ) {
// boolean
if ( isReadMethod ) {
code.addInvokeinterface(
callbackTypeIndex,
"readBoolean",
"(Ljava/lang/Object;Ljava/lang/String;Z)Z",
4
);
}
else {
code.addInvokeinterface(
callbackTypeIndex,
"writeBoolean",
"(Ljava/lang/Object;Ljava/lang/String;ZZ)Z",
5
);
}
}
else if ( typeName.equals( "B" ) ) {
// byte
if ( isReadMethod ) {
code.addInvokeinterface(
callbackTypeIndex,
"readByte",
"(Ljava/lang/Object;Ljava/lang/String;B)B",
4
);
}
else {
code.addInvokeinterface(
callbackTypeIndex,
"writeByte",
"(Ljava/lang/Object;Ljava/lang/String;BB)B",
5
);
}
}
else if ( typeName.equals( "C" ) ) {
// char
if ( isReadMethod ) {
code.addInvokeinterface(
callbackTypeIndex,
"readChar",
"(Ljava/lang/Object;Ljava/lang/String;C)C",
4
);
}
else {
code.addInvokeinterface(
callbackTypeIndex,
"writeChar",
"(Ljava/lang/Object;Ljava/lang/String;CC)C",
5
);
}
}
else if ( typeName.equals( "I" ) ) {
// int
if ( isReadMethod ) {
code.addInvokeinterface(
callbackTypeIndex,
"readInt",
"(Ljava/lang/Object;Ljava/lang/String;I)I",
4
);
}
else {
code.addInvokeinterface(
callbackTypeIndex,
"writeInt",
"(Ljava/lang/Object;Ljava/lang/String;II)I",
5
);
}
}
else if ( typeName.equals( "S" ) ) {
// short
if ( isReadMethod ) {
code.addInvokeinterface(
callbackTypeIndex,
"readShort",
"(Ljava/lang/Object;Ljava/lang/String;S)S",
4
);
}
else {
code.addInvokeinterface(
callbackTypeIndex,
"writeShort",
"(Ljava/lang/Object;Ljava/lang/String;SS)S",
5
);
}
}
else if ( typeName.equals( "D" ) ) {
// double
if ( isReadMethod ) {
code.addInvokeinterface(
callbackTypeIndex,
"readDouble",
"(Ljava/lang/Object;Ljava/lang/String;D)D",
5
);
}
else {
code.addInvokeinterface(
callbackTypeIndex,
"writeDouble",
"(Ljava/lang/Object;Ljava/lang/String;DD)D",
7
);
}
}
else if ( typeName.equals( "F" ) ) {
// float
if ( isReadMethod ) {
code.addInvokeinterface(
callbackTypeIndex,
"readFloat",
"(Ljava/lang/Object;Ljava/lang/String;F)F",
4
);
}
else {
code.addInvokeinterface(
callbackTypeIndex,
"writeFloat",
"(Ljava/lang/Object;Ljava/lang/String;FF)F",
5
);
}
}
else if ( typeName.equals( "J" ) ) {
// long
if ( isReadMethod ) {
code.addInvokeinterface(
callbackTypeIndex,
"readLong",
"(Ljava/lang/Object;Ljava/lang/String;J)J",
5
);
}
else {
code.addInvokeinterface(
callbackTypeIndex,
"writeLong",
"(Ljava/lang/Object;Ljava/lang/String;JJ)J",
7
);
}
}
else {
// bad type
throw new RuntimeException( "bad type: " + typeName );
}
}
private static void addTypeDependDataLoad(Bytecode code, String typeName, int i) {
if ( typeName.charAt( 0 ) == 'L'
&& typeName.charAt( typeName.length() - 1 ) == ';'
|| typeName.charAt( 0 ) == '[' ) {
// reference type
code.addAload( i );
}
else if ( typeName.equals( "Z" )
|| typeName.equals( "B" )
|| typeName.equals( "C" )
|| typeName.equals( "I" )
|| typeName.equals( "S" ) ) {
// boolean, byte, char, int, short
code.addIload( i );
}
else if ( typeName.equals( "D" ) ) {
// double
code.addDload( i );
}
else if ( typeName.equals( "F" ) ) {
// float
code.addFload( i );
}
else if ( typeName.equals( "J" ) ) {
// long
code.addLload( i );
}
else {
// bad type
throw new RuntimeException( "bad type: " + typeName );
}
}
private static void addTypeDependDataStore(Bytecode code, String typeName, int i) {
if ( typeName.charAt( 0 ) == 'L'
&& typeName.charAt( typeName.length() - 1 ) == ';'
|| typeName.charAt( 0 ) == '[' ) {
// reference type
code.addAstore( i );
}
else if ( typeName.equals( "Z" )
|| typeName.equals( "B" )
|| typeName.equals( "C" )
|| typeName.equals( "I" )
|| typeName.equals( "S" ) ) {
// boolean, byte, char, int, short
code.addIstore( i );
}
else if ( typeName.equals( "D" ) ) {
// double
code.addDstore( i );
}
else if ( typeName.equals( "F" ) ) {
// float
code.addFstore( i );
}
else if ( typeName.equals( "J" ) ) {
// long
code.addLstore( i );
}
else {
// bad type
throw new RuntimeException( "bad type: " + typeName );
}
}
private static void addTypeDependDataReturn(Bytecode code, String typeName) {
if ( typeName.charAt( 0 ) == 'L'
&& typeName.charAt( typeName.length() - 1 ) == ';'
|| typeName.charAt( 0 ) == '[') {
// reference type
code.addOpcode( Opcode.ARETURN );
}
else if ( typeName.equals( "Z" )
|| typeName.equals( "B" )
|| typeName.equals( "C" )
|| typeName.equals( "I" )
|| typeName.equals( "S" ) ) {
// boolean, byte, char, int, short
code.addOpcode( Opcode.IRETURN );
}
else if ( typeName.equals( "D" ) ) {
// double
code.addOpcode( Opcode.DRETURN );
}
else if ( typeName.equals( "F" ) ) {
// float
code.addOpcode( Opcode.FRETURN );
}
else if ( typeName.equals( "J" ) ) {
// long
code.addOpcode( Opcode.LRETURN );
}
else {
// bad type
throw new RuntimeException( "bad type: " + typeName );
}
}
}

View File

@ -1,145 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.internal.javassist;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.ProtectionDomain;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.bytecode.ClassFile;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.buildtime.spi.ClassFilter;
import org.hibernate.bytecode.spi.AbstractClassTransformerImpl;
import org.hibernate.internal.CoreMessageLogger;
import org.jboss.logging.Logger;
/**
* Enhance the classes allowing them to implements InterceptFieldEnabled
* This interface is then used by Hibernate for some optimizations.
*
* @author Emmanuel Bernard
* @author Steve Ebersole
* @author Dustin Schultz
*/
public class JavassistClassTransformer extends AbstractClassTransformerImpl {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
JavassistClassTransformer.class.getName()
);
/**
* Constructs the JavassistClassTransformer
*
* @param classFilter The filter used to determine which classes to transform
* @param fieldFilter The filter used to determine which fields to transform
*/
public JavassistClassTransformer(ClassFilter classFilter, org.hibernate.bytecode.buildtime.spi.FieldFilter fieldFilter) {
super( classFilter, fieldFilter );
}
@Override
protected byte[] doTransform(
ClassLoader loader,
String className,
Class classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
ClassFile classfile;
try {
// WARNING: classfile only
classfile = new ClassFile( new DataInputStream( new ByteArrayInputStream( classfileBuffer ) ) );
}
catch (IOException e) {
LOG.unableToBuildEnhancementMetamodel( className );
return classfileBuffer;
}
final ClassPool cp = new ClassPool();
cp.appendSystemPath();
cp.appendClassPath( new ClassClassPath( this.getClass() ) );
cp.appendClassPath( new ClassClassPath( classfile.getClass() ) );
try {
cp.makeClassIfNew( new ByteArrayInputStream( classfileBuffer ) );
}
catch (IOException e) {
throw new RuntimeException( e.getMessage(), e );
}
final FieldTransformer transformer = getFieldTransformer( classfile, cp );
if ( transformer != null ) {
LOG.debugf( "Enhancing %s", className );
DataOutputStream out = null;
try {
transformer.transform( classfile );
final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
out = new DataOutputStream( byteStream );
classfile.write( out );
return byteStream.toByteArray();
}
catch (Exception e) {
LOG.unableToTransformClass( e.getMessage() );
throw new HibernateException( "Unable to transform class: " + e.getMessage() );
}
finally {
try {
if ( out != null ) {
out.close();
}
}
catch (IOException e) {
//swallow
}
}
}
return classfileBuffer;
}
protected FieldTransformer getFieldTransformer(final ClassFile classfile, final ClassPool classPool) {
if ( alreadyInstrumented( classfile ) ) {
return null;
}
return new FieldTransformer(
new FieldFilter() {
public boolean handleRead(String desc, String name) {
return fieldFilter.shouldInstrumentField( classfile.getName(), name );
}
public boolean handleWrite(String desc, String name) {
return fieldFilter.shouldInstrumentField( classfile.getName(), name );
}
public boolean handleReadAccess(String fieldOwnerClassName, String fieldName) {
return fieldFilter.shouldTransformFieldAccess( classfile.getName(), fieldOwnerClassName, fieldName );
}
public boolean handleWriteAccess(String fieldOwnerClassName, String fieldName) {
return fieldFilter.shouldTransformFieldAccess( classfile.getName(), fieldOwnerClassName, fieldName );
}
},
classPool
);
}
private boolean alreadyInstrumented(ClassFile classfile) {
final String[] interfaces = classfile.getInterfaces();
for ( String anInterface : interfaces ) {
if ( FieldHandled.class.getName().equals( anInterface ) ) {
return true;
}
}
return false;
}
}

View File

@ -1,70 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.internal.javassist;
import java.io.IOException;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import org.hibernate.HibernateException;
/**
* A ClassLoader implementation applying Class transformations as they are being loaded.
*
* @author Steve Ebersole
*/
@SuppressWarnings("UnusedDeclaration")
public class TransformingClassLoader extends ClassLoader {
private ClassLoader parent;
private ClassPool classPool;
TransformingClassLoader(ClassLoader parent, String[] classpaths) {
this.parent = parent;
this.classPool = new ClassPool( true );
for ( String classpath : classpaths ) {
try {
classPool.appendClassPath( classpath );
}
catch (NotFoundException e) {
throw new HibernateException(
"Unable to resolve requested classpath for transformation [" +
classpath + "] : " + e.getMessage()
);
}
}
}
@Override
protected Class findClass(String name) throws ClassNotFoundException {
try {
final CtClass cc = classPool.get( name );
// todo : modify the class definition if not already transformed...
final byte[] b = cc.toBytecode();
return defineClass( name, b, 0, b.length );
}
catch (NotFoundException e) {
throw new ClassNotFoundException();
}
catch (IOException e) {
throw new ClassNotFoundException();
}
catch (CannotCompileException e) {
throw new ClassNotFoundException();
}
}
/**
* Used to release resources. Call when done with the ClassLoader
*/
public void release() {
classPool = null;
parent = null;
}
}

View File

@ -1,63 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.spi;
import java.security.ProtectionDomain;
import org.hibernate.bytecode.buildtime.spi.ClassFilter;
import org.hibernate.bytecode.buildtime.spi.FieldFilter;
/**
* Basic implementation of the {@link ClassTransformer} contract.
*
* @author Emmanuel Bernard
* @author Steve Ebersole
*/
public abstract class AbstractClassTransformerImpl implements ClassTransformer {
protected final ClassFilter classFilter;
protected final FieldFilter fieldFilter;
protected AbstractClassTransformerImpl(ClassFilter classFilter, FieldFilter fieldFilter) {
this.classFilter = classFilter;
this.fieldFilter = fieldFilter;
}
@Override
public byte[] transform(
ClassLoader loader,
String className,
Class classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
// to be safe...
className = className.replace( '/', '.' );
if ( classFilter.shouldInstrumentClass( className ) ) {
return doTransform( loader, className, classBeingRedefined, protectionDomain, classfileBuffer );
}
else {
return classfileBuffer;
}
}
/**
* Delegate the transformation call from {@link #transform}
*
* @param loader The class loader to use
* @param className The name of the class to transform
* @param classBeingRedefined If an already loaded class is being redefined, then pass this as a parameter
* @param protectionDomain The protection domain of the class being (re)defined
* @param classfileBuffer The bytes of the class file.
*
* @return The transformed (enhanced/instrumented) bytes.
*/
protected abstract byte[] doTransform(
ClassLoader loader,
String className,
Class classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer);
}

View File

@ -0,0 +1,61 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.spi;
import java.util.Set;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.engine.spi.SessionImplementor;
/**
* Encapsulates bytecode enhancement information about a particular entity.
*
* @author Steve Ebersole
*/
public interface BytecodeEnhancementMetadata {
/**
* The name of the entity to which this metadata applies.
*
* @return The entity name
*/
String getEntityName();
/**
* Has the entity class been bytecode enhanced for lazy loading?
*
* @return {@code true} indicates the entity class is enhanced for Hibernate use
* in lazy loading; {@code false} indicates it is not
*/
boolean isEnhancedForLazyLoading();
/**
* Build and inject an interceptor instance into the enhanced entity.
*
* @param entity The entity into which built interceptor should be injected
* @param uninitializedFieldNames The name of fields marked as lazy
* @param session The session to which the entity instance belongs.
*
* @return The built and injected interceptor
*
* @throws NotInstrumentedException Thrown if {@link #isEnhancedForLazyLoading()} returns {@code false}
*/
LazyAttributeLoadingInterceptor injectInterceptor(
Object entity,
Set<String> uninitializedFieldNames,
SessionImplementor session) throws NotInstrumentedException;
/**
* Extract the field interceptor instance from the enhanced entity.
*
* @param entity The entity from which to extract the interceptor
*
* @return The extracted interceptor
*
* @throws NotInstrumentedException Thrown if {@link #isEnhancedForLazyLoading()} returns {@code false}
*/
LazyAttributeLoadingInterceptor extractInterceptor(Object entity) throws NotInstrumentedException;
}

View File

@ -6,16 +6,12 @@
*/
package org.hibernate.bytecode.spi;
import org.hibernate.bytecode.buildtime.spi.ClassFilter;
import org.hibernate.bytecode.buildtime.spi.FieldFilter;
/**
* Contract for providers of bytecode services to Hibernate.
* <p/>
* Bytecode requirements break down into basically 3 areas<ol>
* Bytecode requirements break down into the following areas<ol>
* <li>proxy generation (both for runtime-lazy-loading and basic proxy generation) {@link #getProxyFactoryFactory()}</li>
* <li>bean reflection optimization {@link #getReflectionOptimizer}</li>
* <li>field-access instrumentation {@link #getTransformer}</li>
* </ol>
*
* @author Steve Ebersole
@ -27,7 +23,7 @@ public interface BytecodeProvider {
*
* @return The provider specific factory.
*/
public ProxyFactoryFactory getProxyFactoryFactory();
ProxyFactoryFactory getProxyFactoryFactory();
/**
* Retrieve the ReflectionOptimizer delegate for this provider
@ -39,26 +35,5 @@ public interface BytecodeProvider {
* @param types The types of all properties to be accessed.
* @return The reflection optimization delegate.
*/
public ReflectionOptimizer getReflectionOptimizer(Class clazz, String[] getterNames, String[] setterNames, Class[] types);
/**
* Generate a ClassTransformer capable of performing bytecode manipulation.
*
* @param classFilter filter used to limit which classes are to be instrumented
* via this ClassTransformer.
* @param fieldFilter filter used to limit which fields are to be instrumented
* via this ClassTransformer.
* @return The appropriate ClassTransformer.
*/
public ClassTransformer getTransformer(ClassFilter classFilter, FieldFilter fieldFilter);
/**
* Retrieve the interception metadata for the particular entity type.
*
* @param entityClass The entity class. Note: we pass class here instead of the usual "entity name" because
* only real classes can be instrumented.
*
* @return The metadata
*/
public EntityInstrumentationMetadata getEntityInstrumentationMetadata(Class entityClass);
ReflectionOptimizer getReflectionOptimizer(Class clazz, String[] getterNames, String[] setterNames, Class[] types);
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.bytecode.spi;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
/**
@ -18,21 +19,22 @@ import java.security.ProtectionDomain;
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Emmanuel Bernard
*/
public interface ClassTransformer {
public interface ClassTransformer extends javax.persistence.spi.ClassTransformer {
/**
* Invoked when a class is being loaded or redefined to add hooks for persistence bytecode manipulation.
*
* @param loader the defining class loaderof the class being transformed. It may be null if using bootstrap loader
* @param classname The name of the class being transformed
* @param className The name of the class being transformed
* @param classBeingRedefined If an already loaded class is being redefined, then pass this as a parameter
* @param protectionDomain ProtectionDomain of the class being (re)-defined
* @param classfileBuffer The input byte buffer in class file format
* @return A well-formed class file that can be loaded
*/
@Override
public byte[] transform(
ClassLoader loader,
String classname,
Class classBeingRedefined,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer);
byte[] classfileBuffer) throws IllegalClassFormatException;
}

View File

@ -1,63 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.spi;
import java.util.Set;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.engine.spi.SessionImplementor;
/**
* Encapsulates bytecode instrumentation information about a particular entity.
*
* @author Steve Ebersole
*/
public interface EntityInstrumentationMetadata {
/**
* The name of the entity to which this metadata applies.
*
* @return The entity name
*/
public String getEntityName();
/**
* Has the entity class been bytecode instrumented?
*
* @return {@code true} indicates the entity class is instrumented for Hibernate use; {@code false}
* indicates it is not
*/
public boolean isInstrumented();
/**
* Build and inject a field interceptor instance into the instrumented entity.
*
* @param entity The entity into which built interceptor should be injected
* @param entityName The name of the entity
* @param uninitializedFieldNames The name of fields marked as lazy
* @param session The session to which the entity instance belongs.
*
* @return The built and injected interceptor
*
* @throws NotInstrumentedException Thrown if {@link #isInstrumented()} returns {@code false}
*/
public FieldInterceptor injectInterceptor(
Object entity,
String entityName,
Set uninitializedFieldNames,
SessionImplementor session) throws NotInstrumentedException;
/**
* Extract the field interceptor instance from the instrumented entity.
*
* @param entity The entity from which to extract the interceptor
*
* @return The extracted interceptor
*
* @throws NotInstrumentedException Thrown if {@link #isInstrumented()} returns {@code false}
*/
public FieldInterceptor extractInterceptor(Object entity) throws NotInstrumentedException;
}

View File

@ -16,7 +16,6 @@ import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityEntryExtraState;
@ -279,13 +278,6 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
getPersister().setPropertyValue( entity, getPersister().getVersionProperty(), nextVersion );
}
if ( getPersister().getInstrumentationMetadata().isInstrumented() ) {
final FieldInterceptor interceptor = getPersister().getInstrumentationMetadata().extractInterceptor( entity );
if ( interceptor != null ) {
interceptor.clearDirty();
}
}
if( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
@ -340,7 +332,7 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
@SuppressWarnings( {"SimplifiableIfStatement"})
private boolean isUnequivocallyNonDirty(Object entity) {
if (entity instanceof SelfDirtinessTracker) {
if ( entity instanceof SelfDirtinessTracker ) {
return ! ( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes();
}
@ -354,11 +346,6 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
return false;
}
if ( getPersister().getInstrumentationMetadata().isInstrumented() ) {
// the entity must be instrumented (otherwise we cant check dirty flag) and the dirty flag is false
return ! getPersister().getInstrumentationMetadata().extractInterceptor( entity ).isDirty();
}
return false;
}

View File

@ -11,7 +11,7 @@ import java.io.Serializable;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.TransientObjectException;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.persister.entity.EntityPersister;

View File

@ -10,7 +10,7 @@ import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.PropertyValueException;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.persister.entity.EntityPersister;

View File

@ -31,7 +31,7 @@ import org.hibernate.NonUniqueObjectException;
import org.hibernate.PersistentObjectException;
import org.hibernate.TransientObjectException;
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoader;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.collection.spi.PersistentCollection;
@ -226,8 +226,8 @@ public class StatefulPersistenceContext implements PersistenceContext {
// todo : I dont think this need be reentrant safe
if ( objectEntityEntryEntry.getKey() instanceof PersistentAttributeInterceptable ) {
final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) objectEntityEntryEntry.getKey() ).$$_hibernate_getInterceptor();
if ( interceptor instanceof LazyAttributeLoader ) {
( (LazyAttributeLoader) interceptor ).unsetSession();
if ( interceptor instanceof LazyAttributeLoadingInterceptor ) {
( (LazyAttributeLoadingInterceptor) interceptor ).unsetSession();
}
}
}

View File

@ -12,7 +12,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.CacheMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.engine.spi.EntityEntry;

View File

@ -14,7 +14,6 @@ import org.hibernate.NonUniqueObjectException;
import org.hibernate.action.internal.AbstractEntityInsertAction;
import org.hibernate.action.internal.EntityIdentityInsertAction;
import org.hibernate.action.internal.EntityInsertAction;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.classic.Lifecycle;
import org.hibernate.engine.internal.Cascade;
import org.hibernate.engine.internal.CascadePoint;
@ -288,8 +287,6 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
insert.handleNaturalIdPostSaveNotifications( id );
}
markInterceptorDirty( entity, persister, source );
EntityEntry newEntry = source.getPersistenceContext().getEntry( entity );
if ( newEntry != original ) {
@ -327,18 +324,6 @@ public abstract class AbstractSaveEventListener extends AbstractReassociateEvent
}
}
private void markInterceptorDirty(Object entity, EntityPersister persister, EventSource source) {
if ( persister.getInstrumentationMetadata().isInstrumented() ) {
FieldInterceptor interceptor = persister.getInstrumentationMetadata().injectInterceptor(
entity,
persister.getEntityName(),
null,
source
);
interceptor.dirty();
}
}
protected Map getMergeMap(Object anything) {
return null;
}

View File

@ -7,7 +7,7 @@
package org.hibernate.event.internal;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.event.spi.EventSource;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.CollectionType;

View File

@ -217,12 +217,8 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
return true;
}
else {
if ( event.getEntityEntry().getPersister().getInstrumentationMetadata().isInstrumented() ) {
event.getEntityEntry()
.getPersister()
.getInstrumentationMetadata()
.extractInterceptor( event.getEntity() )
.clearDirty();
if ( SelfDirtinessTracker.class.isInstance( event.getEntity() ) ) {
( (SelfDirtinessTracker) event.getEntity() ).$$_hibernate_clearDirtyAttributes();
}
event.getSession()
.getFactory()

View File

@ -15,7 +15,6 @@ import org.hibernate.ObjectDeletedException;
import org.hibernate.StaleObjectStateException;
import org.hibernate.WrongClassException;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.internal.Cascade;
import org.hibernate.engine.internal.CascadePoint;
@ -336,13 +335,6 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
}
private void markInterceptorDirty(final Object entity, final Object target, EntityPersister persister) {
if ( persister.getInstrumentationMetadata().isInstrumented() ) {
FieldInterceptor interceptor = persister.getInstrumentationMetadata().extractInterceptor( target );
if ( interceptor != null ) {
interceptor.dirty();
}
}
// for enhanced entities, copy over the dirty attributes
if ( entity instanceof SelfDirtinessTracker && target instanceof SelfDirtinessTracker ) {
// clear, because setting the embedded attributes dirties them

View File

@ -201,12 +201,12 @@ public interface DeprecationLogger extends BasicLogger {
)
void logDeprecatedTransactionFactorySetting(String legacySettingName, String updatedSettingName);
@LogMessage(level = WARN)
@Message(
id = 90000019,
value = "You are using the deprecated legacy bytecode enhancement feature which has been superseded by a vastly improved bytecode enhancer."
)
void logDeprecatedBytecodeEnhancement();
// @LogMessage(level = WARN)
// @Message(
// id = 90000019,
// value = "You are using the deprecated legacy bytecode enhancement feature which has been superseded by a vastly improved bytecode enhancer."
// )
// void logDeprecatedBytecodeEnhancement();
}

View File

@ -10,7 +10,7 @@ import java.util.HashMap;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.TypedValue;

View File

@ -33,10 +33,9 @@ import org.hibernate.QueryException;
import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
import org.hibernate.StaleStateException;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoader;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
import org.hibernate.cache.spi.entry.CacheEntry;
@ -66,8 +65,6 @@ import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.PersistenceContext.NaturalIdHelper;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.ValueInclusion;
@ -577,7 +574,7 @@ public abstract class AbstractEntityPersister
// PROPERTIES
final boolean lazyAvailable = isInstrumented() || entityMetamodel.isLazyLoadingBytecodeEnhanced();
final boolean lazyAvailable = isInstrumented();
int hydrateSpan = entityMetamodel.getPropertySpan();
propertyColumnSpans = new int[hydrateSpan];
@ -4244,27 +4241,17 @@ public abstract class AbstractEntityPersister
// }
public void afterReassociate(Object entity, SessionImplementor session) {
if ( getEntityMetamodel().getInstrumentationMetadata().isInstrumented() ) {
FieldInterceptor interceptor = getEntityMetamodel().getInstrumentationMetadata()
.extractInterceptor( entity );
if ( interceptor != null ) {
interceptor.setSession( session );
}
else {
FieldInterceptor fieldInterceptor = getEntityMetamodel().getInstrumentationMetadata().injectInterceptor(
if ( getEntityMetamodel().getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
LazyAttributeLoadingInterceptor interceptor = getEntityMetamodel().getBytecodeEnhancementMetadata().extractInterceptor( entity );
if ( interceptor == null ) {
getEntityMetamodel().getBytecodeEnhancementMetadata().injectInterceptor(
entity,
getEntityName(),
null,
session
);
fieldInterceptor.dirty();
}
}
if ( entity instanceof PersistentAttributeInterceptable ) {
PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
if ( interceptor != null && interceptor instanceof LazyAttributeLoader ) {
( (LazyAttributeLoader) interceptor ).setSession( session );
else {
interceptor.setSession( session );
}
}
@ -4378,7 +4365,7 @@ public abstract class AbstractEntityPersister
public boolean hasProxy() {
// skip proxy instantiation if entity is bytecode enhanced
return entityMetamodel.isLazy() && !entityMetamodel.isLazyLoadingBytecodeEnhanced();
return entityMetamodel.isLazy() && !entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
}
public IdentifierGenerator getIdentifierGenerator() throws HibernateException {
@ -4477,7 +4464,7 @@ public abstract class AbstractEntityPersister
}
public boolean isInstrumented() {
return entityMetamodel.isInstrumented();
return entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
}
public boolean hasInsertGeneratedProperties() {
@ -5101,8 +5088,8 @@ public abstract class AbstractEntityPersister
}
@Override
public EntityInstrumentationMetadata getInstrumentationMetadata() {
return entityMetamodel.getInstrumentationMetadata();
public BytecodeEnhancementMetadata getInstrumentationMetadata() {
return entityMetamodel.getBytecodeEnhancementMetadata();
}
@Override

View File

@ -14,7 +14,7 @@ import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cache.spi.OptimisticCacheSource;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
@ -779,7 +779,7 @@ public interface EntityPersister extends OptimisticCacheSource, EntityDefinition
public EntityMode getEntityMode();
public EntityTuplizer getEntityTuplizer();
public EntityInstrumentationMetadata getInstrumentationMetadata();
public BytecodeEnhancementMetadata getInstrumentationMetadata();
public FilterAliasGenerator getFilterAliasGenerator(final String rootAlias);

View File

@ -14,7 +14,7 @@ import java.lang.reflect.Method;
import java.util.Map;
import org.hibernate.PropertyAccessException;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoader;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SessionImplementor;
@ -41,8 +41,8 @@ public class EnhancedGetterMethodImpl implements Getter {
private boolean isAttributeLoaded(Object owner) {
if ( owner instanceof PersistentAttributeInterceptable ) {
PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) owner ).$$_hibernate_getInterceptor();
if ( interceptor != null && interceptor instanceof LazyAttributeLoader ) {
return ( (LazyAttributeLoader) interceptor ).isAttributeLoaded( propertyName );
if ( interceptor != null && interceptor instanceof LazyAttributeLoadingInterceptor ) {
return ( (LazyAttributeLoadingInterceptor) interceptor ).isAttributeLoaded( propertyName );
}
}
return true;

View File

@ -1,120 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.tool.instrument;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.hibernate.bytecode.buildtime.spi.Instrumenter;
import org.hibernate.bytecode.buildtime.spi.Logger;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
/**
* Super class for all Hibernate instrumentation tasks. Provides the basic templating of how instrumentation
* should occur; subclasses simply plug in to that process appropriately for the given bytecode provider.
*
* @author Steve Ebersole
*/
public abstract class BasicInstrumentationTask extends Task implements Instrumenter.Options {
private final LoggerBridge logger = new LoggerBridge();
private List filesets = new ArrayList();
private boolean extended;
// deprecated option...
private boolean verbose;
public void addFileset(FileSet set) {
this.filesets.add( set );
}
protected final Iterator filesets() {
return filesets.iterator();
}
public boolean isExtended() {
return extended;
}
public void setExtended(boolean extended) {
this.extended = extended;
}
public boolean isVerbose() {
return verbose;
}
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
public final boolean performExtendedInstrumentation() {
return isExtended();
}
protected abstract Instrumenter buildInstrumenter(Logger logger, Instrumenter.Options options);
@Override
public void execute() throws BuildException {
try {
buildInstrumenter( logger, this )
.execute( collectSpecifiedFiles() );
}
catch ( Throwable t ) {
throw new BuildException( t );
}
}
private Set collectSpecifiedFiles() {
HashSet files = new HashSet();
Project project = getProject();
Iterator filesets = filesets();
while ( filesets.hasNext() ) {
FileSet fs = ( FileSet ) filesets.next();
DirectoryScanner ds = fs.getDirectoryScanner( project );
String[] includedFiles = ds.getIncludedFiles();
File d = fs.getDir( project );
for ( int i = 0; i < includedFiles.length; ++i ) {
files.add( new File( d, includedFiles[i] ) );
}
}
return files;
}
protected class LoggerBridge implements Logger {
public void trace(String message) {
log( message, Project.MSG_VERBOSE );
}
public void debug(String message) {
log( message, Project.MSG_DEBUG );
}
public void info(String message) {
log( message, Project.MSG_INFO );
}
public void warn(String message) {
log( message, Project.MSG_WARN );
}
public void error(String message) {
log( message, Project.MSG_ERR );
}
}
}

View File

@ -1,54 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.tool.instrument.javassist;
import org.hibernate.bytecode.buildtime.internal.JavassistInstrumenter;
import org.hibernate.bytecode.buildtime.spi.Instrumenter;
import org.hibernate.bytecode.buildtime.spi.Logger;
import org.hibernate.tool.instrument.BasicInstrumentationTask;
/**
* An Ant task for instrumenting persistent classes in order to enable
* field-level interception using Javassist.
* <p/>
* In order to use this task, typically you would define a a taskdef
* similiar to:<pre>
* <taskdef name="instrument" classname="org.hibernate.tool.instrument.javassist.InstrumentTask">
* <classpath refid="lib.class.path"/>
* </taskdef>
* </pre>
* where <tt>lib.class.path</tt> is an ANT path reference containing all the
* required Hibernate and Javassist libraries.
* <p/>
* And then use it like:<pre>
* <instrument verbose="true">
* <fileset dir="${testclasses.dir}/org/hibernate/test">
* <include name="yadda/yadda/**"/>
* ...
* </fileset>
* </instrument>
* </pre>
* where the nested ANT fileset includes the class you would like to have
* instrumented.
* <p/>
* Optionally you can chose to enable "Extended Instrumentation" if desired
* by specifying the extended attriubute on the task:<pre>
* <instrument verbose="true" extended="true">
* ...
* </instrument>
* </pre>
* See the Hibernate manual regarding this option.
*
* @author Muga Nishizawa
* @author Steve Ebersole
*/
public class InstrumentTask extends BasicInstrumentationTask {
@Override
protected Instrumenter buildInstrumenter(Logger logger, Instrumenter.Options options) {
return new JavassistInstrumenter( logger, options );
}
}

View File

@ -1,18 +0,0 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<html>
<head></head>
<body>
<p>
The <tt>instrument</tt> tool for adding field-interception hooks
to persistent classes using built-time bytecode processing. Use
this tool only if you wish to take advantage of lazy property
fetching (the <tt>&lt;lazy&gt;</tt> mapping element).
</p>
</body>
</html>

View File

@ -14,7 +14,7 @@ import java.util.Set;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
@ -153,7 +153,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
instantiator = buildInstantiator( mappingInfo );
if ( entityMetamodel.isLazy() && !entityMetamodel.isLazyLoadingBytecodeEnhanced() ) {
if ( entityMetamodel.isLazy() && !entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
proxyFactory = buildProxyFactory( mappingInfo, idGetter, idSetter );
if ( proxyFactory == null ) {
entityMetamodel.setLazy( false );
@ -657,7 +657,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
@Override
public boolean hasProxy() {
return entityMetamodel.isLazy() && !entityMetamodel.isLazyLoadingBytecodeEnhanced();
return entityMetamodel.isLazy() && !entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
}
@Override

View File

@ -0,0 +1,50 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.tuple.entity;
import java.util.Set;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.bytecode.spi.NotInstrumentedException;
import org.hibernate.engine.spi.SessionImplementor;
/**
* @author Steve Ebersole
*/
public class BytecodeEnhancementMetadataNonEnhancedPojoImpl implements BytecodeEnhancementMetadata {
private final Class entityClass;
private final String errorMsg;
public BytecodeEnhancementMetadataNonEnhancedPojoImpl(Class entityClass) {
this.entityClass = entityClass;
this.errorMsg = "Entity class [" + entityClass.getName() + "] is not enhanced";
}
@Override
public String getEntityName() {
return entityClass.getName();
}
@Override
public boolean isEnhancedForLazyLoading() {
return false;
}
@Override
public LazyAttributeLoadingInterceptor injectInterceptor(
Object entity,
Set<String> uninitializedFieldNames,
SessionImplementor session) throws NotInstrumentedException {
throw new NotInstrumentedException( errorMsg );
}
@Override
public LazyAttributeLoadingInterceptor extractInterceptor(Object entity) throws NotInstrumentedException {
throw new NotInstrumentedException( errorMsg );
}
}

View File

@ -8,19 +8,19 @@ package org.hibernate.tuple.entity;
import java.util.Set;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.bytecode.spi.NotInstrumentedException;
import org.hibernate.engine.spi.SessionImplementor;
/**
* @author Steve Ebersole
*/
public class NonPojoInstrumentationMetadata implements EntityInstrumentationMetadata {
public class BytecodeEnhancementMetadataNonPojoImpl implements BytecodeEnhancementMetadata {
private final String entityName;
private final String errorMsg;
public NonPojoInstrumentationMetadata(String entityName) {
public BytecodeEnhancementMetadataNonPojoImpl(String entityName) {
this.entityName = entityName;
this.errorMsg = "Entity [" + entityName + "] is non-pojo, and therefore not instrumented";
}
@ -31,19 +31,20 @@ public class NonPojoInstrumentationMetadata implements EntityInstrumentationMeta
}
@Override
public boolean isInstrumented() {
public boolean isEnhancedForLazyLoading() {
return false;
}
@Override
public FieldInterceptor extractInterceptor(Object entity) throws NotInstrumentedException {
public LazyAttributeLoadingInterceptor injectInterceptor(
Object entity,
Set<String> uninitializedFieldNames,
SessionImplementor session) throws NotInstrumentedException {
throw new NotInstrumentedException( errorMsg );
}
@Override
public FieldInterceptor injectInterceptor(
Object entity, String entityName, Set uninitializedFieldNames, SessionImplementor session)
throws NotInstrumentedException {
public LazyAttributeLoadingInterceptor extractInterceptor(Object entity) throws NotInstrumentedException {
throw new NotInstrumentedException( errorMsg );
}
}

View File

@ -0,0 +1,87 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.tuple.entity;
import java.util.Set;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.bytecode.spi.NotInstrumentedException;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SessionImplementor;
/**
* @author Steve Ebersole
*/
public class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhancementMetadata {
private final Class entityClass;
private final boolean enhancedForLazyLoading;
public BytecodeEnhancementMetadataPojoImpl(Class entityClass) {
this.entityClass = entityClass;
this.enhancedForLazyLoading = PersistentAttributeInterceptable.class.isAssignableFrom( entityClass );
}
@Override
public String getEntityName() {
return entityClass.getName();
}
@Override
public boolean isEnhancedForLazyLoading() {
return enhancedForLazyLoading;
}
@Override
public LazyAttributeLoadingInterceptor extractInterceptor(Object entity) throws NotInstrumentedException {
if ( !enhancedForLazyLoading ) {
throw new NotInstrumentedException( "Entity class [" + entityClass.getName() + "] is not enhanced for lazy loading" );
}
if ( !entityClass.isInstance( entity ) ) {
throw new IllegalArgumentException(
String.format(
"Passed entity instance [%s] is not of expected type [%s]",
entity,
getEntityName()
)
);
}
final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
if ( interceptor == null ) {
return null;
}
return (LazyAttributeLoadingInterceptor) interceptor;
}
@Override
public LazyAttributeLoadingInterceptor injectInterceptor(
Object entity,
Set<String> uninitializedFieldNames,
SessionImplementor session) throws NotInstrumentedException {
if ( !enhancedForLazyLoading ) {
throw new NotInstrumentedException( "Entity class [" + entityClass.getName() + "] is not enhanced for lazy loading" );
}
if ( !entityClass.isInstance( entity ) ) {
throw new IllegalArgumentException(
String.format(
"Passed entity instance [%s] is not of expected type [%s]",
entity,
getEntityName()
)
);
}
final LazyAttributeLoadingInterceptor interceptor = new LazyAttributeLoadingInterceptor( session, uninitializedFieldNames, getEntityName() );
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( interceptor );
return interceptor;
}
}

View File

@ -18,13 +18,11 @@ import java.util.Set;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
import org.hibernate.cfg.Environment;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.ValueInclusion;
import org.hibernate.internal.CoreMessageLogger;
@ -124,8 +122,7 @@ public class EntityMetamodel implements Serializable {
private final EntityMode entityMode;
private final EntityTuplizer entityTuplizer;
private final EntityInstrumentationMetadata instrumentationMetadata;
private final boolean lazyLoadingBytecodeEnhanced;
private final BytecodeEnhancementMetadata bytecodeEnhancementMetadata;
public EntityMetamodel(
PersistentClass persistentClass,
@ -145,12 +142,12 @@ public class EntityMetamodel implements Serializable {
versioned = persistentClass.isVersioned();
instrumentationMetadata = persistentClass.hasPojoRepresentation()
? Environment.getBytecodeProvider().getEntityInstrumentationMetadata( persistentClass.getMappedClass() )
: new NonPojoInstrumentationMetadata( persistentClass.getEntityName() );
lazyLoadingBytecodeEnhanced = ( persistentClass.getMappedClass() != null
&& PersistentAttributeInterceptable.class.isAssignableFrom( persistentClass.getMappedClass() ) );
if ( persistentClass.hasPojoRepresentation() ) {
bytecodeEnhancementMetadata = new BytecodeEnhancementMetadataPojoImpl( persistentClass.getMappedClass() );
}
else {
bytecodeEnhancementMetadata = new BytecodeEnhancementMetadataNonPojoImpl( persistentClass.getEntityName() );
}
boolean hasLazy = false;
@ -201,7 +198,7 @@ public class EntityMetamodel implements Serializable {
sessionFactory,
i,
prop,
instrumentationMetadata.isInstrumented()
bytecodeEnhancementMetadata.isEnhancedForLazyLoading()
);
}
else {
@ -210,7 +207,7 @@ public class EntityMetamodel implements Serializable {
sessionFactory,
i,
prop,
instrumentationMetadata.isInstrumented()
bytecodeEnhancementMetadata.isEnhancedForLazyLoading()
);
}
@ -226,7 +223,7 @@ public class EntityMetamodel implements Serializable {
}
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
boolean lazy = prop.isLazy() && ( instrumentationMetadata.isInstrumented() || lazyLoadingBytecodeEnhanced );
boolean lazy = prop.isLazy() && bytecodeEnhancementMetadata.isEnhancedForLazyLoading();
if ( lazy ) {
hasLazy = true;
}
@ -1096,14 +1093,10 @@ public class EntityMetamodel implements Serializable {
* Whether or not this class can be lazy (ie intercepted)
*/
public boolean isInstrumented() {
return instrumentationMetadata.isInstrumented();
return bytecodeEnhancementMetadata.isEnhancedForLazyLoading();
}
public EntityInstrumentationMetadata getInstrumentationMetadata() {
return instrumentationMetadata;
}
public boolean isLazyLoadingBytecodeEnhanced() {
return this.lazyLoadingBytecodeEnhanced;
public BytecodeEnhancementMetadata getBytecodeEnhancementMetadata() {
return bytecodeEnhancementMetadata;
}
}

View File

@ -18,9 +18,7 @@ import org.hibernate.EntityMode;
import org.hibernate.EntityNameResolver;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoader;
import org.hibernate.bytecode.instrumentation.internal.FieldInterceptionHelper;
import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.cfg.Environment;
import org.hibernate.classic.Lifecycle;
@ -57,14 +55,14 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
private final boolean lifecycleImplementor;
private final Set<String> lazyPropertyNames;
private final ReflectionOptimizer optimizer;
private final boolean isInstrumented;
private final boolean isBytecodeEnhanced;
public PojoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
super( entityMetamodel, mappedEntity );
this.mappedClass = mappedEntity.getMappedClass();
this.proxyInterface = mappedEntity.getProxyInterface();
this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedClass );
this.isInstrumented = entityMetamodel.isInstrumented();
this.isBytecodeEnhanced = entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
Iterator iter = mappedEntity.getPropertyClosureIterator();
Set<String> tmpLazyPropertyNames = new HashSet<String>( );
@ -284,23 +282,15 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
@Override
public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {
if ( isInstrumented() ) {
Set<String> lazyProps = lazyPropertiesAreUnfetched && getEntityMetamodel().hasLazyProperties() ?
lazyPropertyNames : null;
//TODO: if we support multiple fetch groups, we would need
// to clone the set of lazy properties!
FieldInterceptionHelper.injectFieldInterceptor( entity, getEntityName(), lazyProps, session );
}
// new bytecode enhancement lazy interception
if ( entity instanceof PersistentAttributeInterceptable ) {
if ( lazyPropertiesAreUnfetched && getEntityMetamodel().hasLazyProperties() ) {
PersistentAttributeInterceptor interceptor = new LazyAttributeLoader( session, lazyPropertyNames, getEntityName() );
PersistentAttributeInterceptor interceptor = new LazyAttributeLoadingInterceptor( session, lazyPropertyNames, getEntityName() );
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( interceptor );
}
}
//also clear the fields that are marked as dirty in the dirtyness tracker
// also clear the fields that are marked as dirty in the dirtyness tracker
if ( entity instanceof SelfDirtinessTracker ) {
( (SelfDirtinessTracker) entity ).$$_hibernate_clearDirtyAttributes();
}
@ -311,21 +301,18 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
if ( getEntityMetamodel().hasLazyProperties() ) {
if ( entity instanceof PersistentAttributeInterceptable ) {
PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) entity ).$$_hibernate_getInterceptor();
if ( interceptor != null && interceptor instanceof LazyAttributeLoader ) {
return ( (LazyAttributeLoader) interceptor ).isUninitialized();
if ( interceptor != null && interceptor instanceof LazyAttributeLoadingInterceptor ) {
return ( (LazyAttributeLoadingInterceptor) interceptor ).hasAnyUninitializedAttributes();
}
}
FieldInterceptor callback = FieldInterceptionHelper.extractFieldInterceptor( entity );
return callback != null && !callback.isInitialized();
}
else {
return false;
}
return false;
}
@Override
public boolean isInstrumented() {
return isInstrumented;
return isBytecodeEnhanced;
}
@Override

View File

@ -9,7 +9,7 @@ package org.hibernate.type;
import java.io.Serializable;
import java.util.Map;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
import org.hibernate.tuple.NonIdentifierAttribute;

View File

@ -15,6 +15,7 @@ import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestTask;
/**
* @author Luis Barreiro

View File

@ -1,135 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.engine.spi.CompositeOwner;
import org.hibernate.engine.spi.CompositeTracker;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.javap.JavapTask;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* utility class to use in bytecode enhancement tests
*
* @author Luis Barreiro
*/
public abstract class DecompileUtils {
private static final CoreMessageLogger log = CoreLogging.messageLogger( DecompileUtils.class );
public static void decompileDumpedClass(String workingDir, String className) {
try {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null );
fileManager.setLocation(
StandardLocation.CLASS_OUTPUT,
Collections.singletonList( new File( workingDir ) )
);
JavapTask javapTask = new JavapTask();
String filename = workingDir + File.separator + getFilenameForClassName( className );
for ( JavaFileObject jfo : fileManager.getJavaFileObjects( filename ) ) {
try {
Set<String> interfaceNames = new HashSet<String>();
Set<String> fieldNames = new HashSet<String>();
Set<String> methodNames = new HashSet<String>();
JavapTask.ClassFileInfo info = javapTask.read( jfo );
log.infof( "decompiled class [%s]", info.cf.getName() );
for ( int i : info.cf.interfaces ) {
interfaceNames.add( info.cf.constant_pool.getClassInfo( i ).getName() );
log.debugf( "declared iFace = ", info.cf.constant_pool.getClassInfo( i ).getName() );
}
for ( com.sun.tools.classfile.Field f : info.cf.fields ) {
fieldNames.add( f.getName( info.cf.constant_pool ) );
log.debugf( "declared field = ", f.getName( info.cf.constant_pool ) );
}
for ( com.sun.tools.classfile.Method m : info.cf.methods ) {
methodNames.add( m.getName( info.cf.constant_pool ) );
log.debugf( "declared method = ", m.getName( info.cf.constant_pool ) );
}
// checks signature against known interfaces
if ( interfaceNames.contains( PersistentAttributeInterceptor.class.getName() ) ) {
assertTrue( fieldNames.contains( EnhancerConstants.INTERCEPTOR_FIELD_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.INTERCEPTOR_GETTER_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.INTERCEPTOR_SETTER_NAME ) );
}
if ( interfaceNames.contains( ManagedEntity.class.getName() ) ) {
assertTrue( methodNames.contains( EnhancerConstants.ENTITY_INSTANCE_GETTER_NAME ) );
assertTrue( fieldNames.contains( EnhancerConstants.ENTITY_ENTRY_FIELD_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.ENTITY_ENTRY_GETTER_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.ENTITY_ENTRY_SETTER_NAME ) );
assertTrue( fieldNames.contains( EnhancerConstants.PREVIOUS_FIELD_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.PREVIOUS_GETTER_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.PREVIOUS_SETTER_NAME ) );
assertTrue( fieldNames.contains( EnhancerConstants.NEXT_FIELD_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.NEXT_GETTER_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.NEXT_SETTER_NAME ) );
}
if ( interfaceNames.contains( SelfDirtinessTracker.class.getName() ) ) {
assertTrue( fieldNames.contains( EnhancerConstants.TRACKER_FIELD_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.TRACKER_CHANGER_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.TRACKER_GET_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.TRACKER_CLEAR_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.TRACKER_HAS_CHANGED_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.TRACKER_SUSPEND_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.TRACKER_COLLECTION_GET_NAME ) );
}
if ( interfaceNames.contains( CompositeTracker.class.getName() ) ) {
assertTrue( fieldNames.contains( EnhancerConstants.TRACKER_COMPOSITE_FIELD_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.TRACKER_COMPOSITE_SET_OWNER ) );
assertTrue( methodNames.contains( EnhancerConstants.TRACKER_COMPOSITE_SET_OWNER ) );
}
if ( interfaceNames.contains( CompositeOwner.class.getName() ) ) {
assertTrue( fieldNames.contains( EnhancerConstants.TRACKER_CHANGER_NAME ) );
assertTrue( methodNames.contains( EnhancerConstants.TRACKER_CHANGER_NAME ) );
}
}
catch (ConstantPoolException e) {
e.printStackTrace();
}
}
}
catch (IOException ioe) {
assertNull( "Failed to open class file", ioe );
}
catch (RuntimeException re) {
log.warnf( re, "WARNING: UNABLE DECOMPILE DUE TO %s", re.getMessage() );
}
}
private static String getFilenameForClassName(String className) {
return className.replace( '.', File.separatorChar ) + JavaFileObject.Kind.CLASS.extension;
}
}

View File

@ -8,6 +8,7 @@ package org.hibernate.test.bytecode.enhancement;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.test.bytecode.enhancement.association.ManyToManyAssociationTestTask;
import org.hibernate.test.bytecode.enhancement.association.OneToManyAssociationTestTask;

View File

@ -9,7 +9,7 @@ package org.hibernate.test.bytecode.enhancement.association;
import java.util.UUID;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
/**

View File

@ -10,7 +10,7 @@ import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertNotNull;

View File

@ -12,7 +12,7 @@ import java.net.URLClassLoader;
import org.hibernate.Session;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
import org.junit.Test;

View File

@ -12,7 +12,7 @@ import java.util.List;
import java.util.Set;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
/**
* @author Luis Barreiro

View File

@ -13,7 +13,7 @@ import javax.persistence.Id;
import javax.persistence.OneToOne;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
/**

View File

@ -16,7 +16,7 @@ import javax.persistence.OneToMany;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.test.bytecode.enhancement.basic.ObjectAttributeMarkerInterceptor;
import org.junit.Assert;

View File

@ -19,7 +19,6 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
/**

View File

@ -7,7 +7,6 @@
package org.hibernate.test.bytecode.enhancement.lazy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.hibernate.Hibernate;
@ -17,8 +16,7 @@ import org.hibernate.cfg.Environment;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;

View File

@ -14,7 +14,7 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
/**

View File

@ -15,7 +15,7 @@ import org.hibernate.cfg.Environment;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
/**

View File

@ -19,7 +19,7 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;

View File

@ -21,7 +21,7 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
/**

View File

@ -10,7 +10,6 @@ import java.util.Arrays;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
@ -26,7 +25,7 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask;
import org.hibernate.test.bytecode.enhancement.EnhancerTestUtils;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;

View File

@ -17,7 +17,7 @@ import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.bytecode.spi.EntityInstrumentationMetadata;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
@ -47,7 +47,7 @@ import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.tuple.entity.NonPojoInstrumentationMetadata;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.type.CollectionType;
import org.hibernate.type.Type;
import org.hibernate.type.VersionType;
@ -87,8 +87,8 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
}
@Override
public EntityInstrumentationMetadata getInstrumentationMetadata() {
return new NonPojoInstrumentationMetadata( null );
public BytecodeEnhancementMetadata getInstrumentationMetadata() {
return new BytecodeEnhancementMetadataNonPojoImpl( null );
}
@Override

View File

@ -1,113 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.buildtime;
import org.junit.Test;
import org.hibernate.bytecode.instrumentation.internal.FieldInterceptionHelper;
import org.hibernate.test.instrument.cases.Executable;
import org.hibernate.test.instrument.cases.TestCustomColumnReadAndWrite;
import org.hibernate.test.instrument.cases.TestDirtyCheckExecutable;
import org.hibernate.test.instrument.cases.TestFetchAllExecutable;
import org.hibernate.test.instrument.cases.TestInjectFieldInterceptorExecutable;
import org.hibernate.test.instrument.cases.TestIsPropertyInitializedExecutable;
import org.hibernate.test.instrument.cases.TestLazyBasicFieldAccessExecutable;
import org.hibernate.test.instrument.cases.TestLazyBasicPropertyAccessExecutable;
import org.hibernate.test.instrument.cases.TestLazyExecutable;
import org.hibernate.test.instrument.cases.TestLazyManyToOneExecutable;
import org.hibernate.test.instrument.cases.TestLazyPropertyCustomTypeExecutable;
import org.hibernate.test.instrument.cases.TestManyToOneProxyExecutable;
import org.hibernate.test.instrument.cases.TestSharedPKOneToOneExecutable;
import org.hibernate.test.instrument.domain.Document;
import org.hibernate.testing.Skip;
import org.hibernate.testing.junit4.BaseUnitTestCase;
/**
* @author Gavin King
*/
@Skip(
message = "domain classes not instrumented for build-time instrumentation testing",
condition = InstrumentTest.SkipCheck.class
)
public class InstrumentTest extends BaseUnitTestCase {
@Test
public void testDirtyCheck() throws Exception {
execute( new TestDirtyCheckExecutable() );
}
@Test
public void testFetchAll() throws Exception {
execute( new TestFetchAllExecutable() );
}
@Test
public void testLazy() throws Exception {
execute( new TestLazyExecutable() );
}
@Test
public void testLazyManyToOne() throws Exception {
execute( new TestLazyManyToOneExecutable() );
}
@Test
public void testSetFieldInterceptor() throws Exception {
execute( new TestInjectFieldInterceptorExecutable() );
}
@Test
public void testPropertyInitialized() throws Exception {
execute( new TestIsPropertyInitializedExecutable() );
}
@Test
public void testManyToOneProxy() throws Exception {
execute( new TestManyToOneProxyExecutable() );
}
@Test
public void testLazyPropertyCustomTypeExecutable() throws Exception {
execute( new TestLazyPropertyCustomTypeExecutable() );
}
@Test
public void testLazyBasicFieldAccess() throws Exception {
execute( new TestLazyBasicFieldAccessExecutable() );
}
@Test
public void testLazyBasicPropertyAccess() throws Exception {
execute( new TestLazyBasicPropertyAccessExecutable() );
}
@Test
public void testSharedPKOneToOne() throws Exception {
execute( new TestSharedPKOneToOneExecutable() );
}
@Test
public void testCustomColumnReadAndWrite() throws Exception {
execute( new TestCustomColumnReadAndWrite() );
}
private void execute(Executable executable) throws Exception {
executable.prepare();
try {
executable.execute();
}
finally {
executable.complete();
}
}
public static class SkipCheck implements Skip.Matcher {
@Override
public boolean isMatch() {
return ! FieldInterceptionHelper.isInstrumented( new Document() );
}
}
}

View File

@ -1,70 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.bytecode.spi.InstrumentedClassLoader;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;
/**
* @author Steve Ebersole
*/
public abstract class AbstractExecutable implements Executable {
private ServiceRegistry serviceRegistry;
private SessionFactory factory;
@Override
public final void prepare() {
BootstrapServiceRegistryBuilder bsrb = new BootstrapServiceRegistryBuilder();
// make sure we pick up the TCCL, and make sure its the isolated CL...
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if ( classLoader == null ) {
throw new RuntimeException( "Isolated ClassLoader not yet set as TCCL" );
}
if ( !InstrumentedClassLoader.class.isInstance( classLoader ) ) {
throw new RuntimeException( "Isolated ClassLoader not yet set as TCCL" );
}
bsrb.applyClassLoader( classLoader );
serviceRegistry = new StandardServiceRegistryBuilder( bsrb.build() )
.applySetting( Environment.HBM2DDL_AUTO, "create-drop" )
.build();
MetadataSources metadataSources = new MetadataSources( serviceRegistry );
for ( String resource : getResources() ) {
metadataSources.addResource( resource );
}
factory = metadataSources.buildMetadata().buildSessionFactory();
}
@Override
public final void complete() {
try {
cleanup();
}
finally {
factory.close();
StandardServiceRegistryBuilder.destroy( serviceRegistry );
}
}
protected SessionFactory getFactory() {
return factory;
}
protected void cleanup() {
}
protected String[] getResources() {
return new String[] { "org/hibernate/test/instrument/domain/Documents.hbm.xml" };
}
}

View File

@ -1,17 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
/**
* @author Steve Ebersole
*/
public interface Executable {
public void prepare();
public void execute() throws Exception;
public void complete();
}

View File

@ -1,76 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.instrument.domain.Document;
import org.hibernate.test.instrument.domain.Folder;
import org.hibernate.test.instrument.domain.Owner;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
/**
* @author Rob.Hasselbaum
*/
public class TestCustomColumnReadAndWrite extends AbstractExecutable {
public void execute() {
Session s = getFactory().openSession();
Transaction t = s.beginTransaction();
final double SIZE_IN_KB = 20480;
final double SIZE_IN_MB = SIZE_IN_KB / 1024d;
Owner o = new Owner();
Document doc = new Document();
Folder fol = new Folder();
o.setName("gavin");
doc.setName("Hibernate in Action");
doc.setSummary("blah");
doc.updateText("blah blah");
fol.setName("books");
doc.setOwner(o);
doc.setFolder(fol);
doc.setSizeKb(SIZE_IN_KB);
fol.getDocuments().add(doc);
s.persist(o);
s.persist(fol);
t.commit();
s.close();
s = getFactory().openSession();
t = s.beginTransaction();
// Check value conversion on insert
// Value returned by Oracle native query is a Types.NUMERIC, which is mapped to a BigDecimalType;
// Cast returned value to Number then call Number.doubleValue() so it works on all dialects.
Double sizeViaSql =
( (Number)s.createSQLQuery("select size_mb from documents").uniqueResult() )
.doubleValue();
assertEquals( SIZE_IN_MB, sizeViaSql, 0.01d );
// Test explicit fetch of all properties
doc = (Document) s.createQuery("from Document fetch all properties").uniqueResult();
assertTrue( Hibernate.isPropertyInitialized( doc, "sizeKb" ) );
assertEquals( SIZE_IN_KB, doc.getSizeKb() );
t.commit();
s.close();
// Test lazy fetch with custom read
s = getFactory().openSession();
t = s.beginTransaction();
doc = (Document) s.get( Document.class, doc.getId() );
assertFalse( Hibernate.isPropertyInitialized( doc, "sizeKb" ) );
assertEquals( SIZE_IN_KB, doc.getSizeKb() );
s.delete(doc);
s.delete( doc.getOwner() );
s.delete( doc.getFolder() );
t.commit();
s.close();
}
}

View File

@ -1,54 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import java.util.Iterator;
import java.util.List;
import junit.framework.Assert;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.instrument.domain.Folder;
/**
* @author Steve Ebersole
*/
public class TestDirtyCheckExecutable extends AbstractExecutable {
public void execute() {
Session s = getFactory().openSession();
Transaction t = s.beginTransaction();
Folder pics = new Folder();
pics.setName("pics");
Folder docs = new Folder();
docs.setName("docs");
s.persist(docs);
s.persist(pics);
t.commit();
s.close();
s = getFactory().openSession();
t = s.beginTransaction();
List list = s.createCriteria(Folder.class).list();
for ( Iterator iter = list.iterator(); iter.hasNext(); ) {
Folder f = (Folder) iter.next();
Assert.assertFalse( f.nameWasread );
}
t.commit();
s.close();
for ( Iterator iter = list.iterator(); iter.hasNext(); ) {
Folder f = (Folder) iter.next();
Assert.assertFalse( f.nameWasread );
}
s = getFactory().openSession();
t = s.beginTransaction();
s.createQuery("delete from Folder").executeUpdate();
t.commit();
s.close();
}
}

View File

@ -1,53 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import junit.framework.Assert;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.instrument.domain.Document;
import org.hibernate.test.instrument.domain.Folder;
import org.hibernate.test.instrument.domain.Owner;
/**
* @author Steve Ebersole
*/
public class TestFetchAllExecutable extends AbstractExecutable {
public void execute() {
Session s = getFactory().openSession();
Transaction t = s.beginTransaction();
Owner o = new Owner();
Document doc = new Document();
Folder fol = new Folder();
o.setName("gavin");
doc.setName("Hibernate in Action");
doc.setSummary("blah");
doc.updateText("blah blah");
fol.setName("books");
doc.setOwner(o);
doc.setFolder(fol);
fol.getDocuments().add(doc);
s.persist(o);
s.persist(fol);
t.commit();
s.close();
s = getFactory().openSession();
t = s.beginTransaction();
doc = (Document) s.createQuery("from Document fetch all properties").uniqueResult();
Assert.assertTrue( Hibernate.isPropertyInitialized( doc, "summary" ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( doc, "upperCaseName" ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( doc, "owner" ) );
Assert.assertEquals( doc.getSummary(), "blah" );
s.delete(doc);
s.delete( doc.getOwner() );
s.delete( doc.getFolder() );
t.commit();
s.close();
}
}

View File

@ -1,175 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.bytecode.spi.InstrumentedClassLoader;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.test.instrument.domain.Passport;
import org.hibernate.test.instrument.domain.Person;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
* @author Steve Ebersole
*/
public class TestFetchingLazyToOneExecutable implements Executable {
private ServiceRegistry serviceRegistry;
private SessionFactory factory;
@Override
public void execute() throws Exception {
doBaselineAssertions();
doFetchNonMappedBySideAssertions();
doFetchMappedBySideAssertions();
}
private void doBaselineAssertions() {
{
// First, load from the non-owning side by id. Person#passport should be uninitialized
Session s = factory.openSession();
s.beginTransaction();
Person person = (Person) s.get( Person.class, 1 );
assertTrue( Hibernate.isInitialized( person ) );
assertFalse( Hibernate.isPropertyInitialized( person, "passport" ) );
assertNotNull( person.getPassport() );
s.getTransaction().commit();
s.close();
}
{
// Then, load from the owning side by id. Passport#person should be uninitialized
Session s = factory.openSession();
s.beginTransaction();
Passport passport = (Passport) s.get( Passport.class, 1 );
assertTrue( Hibernate.isInitialized( passport ) );
assertFalse( Hibernate.isPropertyInitialized( passport, "person" ) );
assertNotNull( passport.getPerson() );
s.getTransaction().commit();
s.close();
}
}
private void doFetchNonMappedBySideAssertions() {
// try to eagerly fetch the association from the owning (non-mappedBy) side
Session s = factory.openSession();
s.beginTransaction();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// the whole question here is design, and whether the `fetch all properties` should be needed
// Passport p = (Passport) s.createQuery( "select p from Passport p join fetch p.person" ).uniqueResult();
// versus:
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Passport p = (Passport) s.createQuery( "select p from Passport p fetch all properties join fetch p.person" ).uniqueResult();
assertTrue( Hibernate.isInitialized( p ) );
assertTrue(
"Assertion that the eager fetch of non-mappedBy association (Passport#person) was performed properly",
Hibernate.isPropertyInitialized( p, "person" )
);
assertNotNull( p.getPerson() );
assertTrue( Hibernate.isInitialized( p.getPerson() ) );
assertSame( p, p.getPerson().getPassport() );
s.getTransaction().commit();
s.close();
}
private void doFetchMappedBySideAssertions() {
// try to eagerly fetch the association from the non-owning (mappedBy) side
Session s = factory.openSession();
s.beginTransaction();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// the whole question here is design, and whether the `fetch all properties` should be needed
// Person p = (Person) s.createQuery( "select p from Person p join fetch p.passport" ).uniqueResult();
// versus:
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Person p = (Person) s.createQuery( "select p from Person p fetch all properties join fetch p.passport" ).uniqueResult();
assertTrue( Hibernate.isInitialized( p ) );
assertTrue(
"Assertion that the eager fetch of mappedBy association (Person#passport) was performed properly",
Hibernate.isPropertyInitialized( p, "passport" )
);
assertNotNull( p.getPassport() );
assertTrue( Hibernate.isInitialized( p.getPassport() ) );
assertSame( p, p.getPassport().getPerson() );
s.getTransaction().commit();
s.close();
}
@Override
public final void prepare() {
BootstrapServiceRegistryBuilder bsrb = new BootstrapServiceRegistryBuilder();
// make sure we pick up the TCCL, and make sure its the isolated CL...
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if ( classLoader == null ) {
throw new RuntimeException( "Isolated ClassLoader not yet set as TCCL" );
}
if ( !InstrumentedClassLoader.class.isInstance( classLoader ) ) {
throw new RuntimeException( "Isolated ClassLoader not yet set as TCCL" );
}
bsrb.applyClassLoader( classLoader );
serviceRegistry = new StandardServiceRegistryBuilder( bsrb.build() )
.applySetting( Environment.HBM2DDL_AUTO, "create-drop" )
.applySetting( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" )
.build();
MetadataSources metadataSources = new MetadataSources( serviceRegistry );
metadataSources.addAnnotatedClass( Person.class );
metadataSources.addAnnotatedClass( Passport.class );
factory = metadataSources.buildMetadata().buildSessionFactory();
createData();
}
private void createData() {
Person steve = new Person( "Steve" );
Passport passport = new Passport( steve, "123456789", "Acme Emirates" );
Session s = factory.openSession();
s.beginTransaction();
s.save( steve );
s.save( passport );
s.getTransaction().commit();
s.close();
}
@Override
public final void complete() {
try {
cleanupData();
}
finally {
factory.close();
StandardServiceRegistryBuilder.destroy( serviceRegistry );
}
}
private void cleanupData() {
Session s = factory.openSession();
s.beginTransaction();
s.createQuery( "delete Passport" ).executeUpdate();
s.createQuery( "delete Person" ).executeUpdate();
s.getTransaction().commit();
s.close();
}
}

View File

@ -1,24 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import java.util.HashSet;
import org.hibernate.bytecode.instrumentation.internal.FieldInterceptionHelper;
import org.hibernate.test.instrument.domain.Document;
/**
* @author Steve Ebersole
*/
public class TestInjectFieldInterceptorExecutable extends AbstractExecutable {
public void execute() {
Document doc = new Document();
FieldInterceptionHelper.injectFieldInterceptor( doc, "Document", new HashSet(), null );
doc.getId();
}
}

View File

@ -1,56 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id: $
package org.hibernate.test.instrument.cases;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.instrument.domain.Document;
import org.hibernate.test.instrument.domain.Folder;
import org.hibernate.test.instrument.domain.Owner;
import junit.framework.Assert;
/**
* @author Steve Ebersole
*/
public class TestIsPropertyInitializedExecutable extends AbstractExecutable {
public void execute() {
Session s = getFactory().openSession();
Transaction t = s.beginTransaction();
Owner o = new Owner();
Document doc = new Document();
Folder fol = new Folder();
o.setName("gavin");
doc.setName("Hibernate in Action");
doc.setSummary("blah");
doc.updateText("blah blah");
fol.setName("books");
doc.setOwner(o);
doc.setFolder(fol);
fol.getDocuments().add(doc);
Assert.assertTrue( Hibernate.isPropertyInitialized( doc, "summary" ) );
s.persist(o);
s.persist(fol);
t.commit();
s.close();
s = getFactory().openSession();
t = s.beginTransaction();
doc = (Document) s.get( Document.class, doc.getId() );
Assert.assertFalse( Hibernate.isPropertyInitialized( doc, "summary" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( doc, "upperCaseName" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( doc, "owner" ) );
s.delete(doc);
s.delete( doc.getOwner() );
s.delete( doc.getFolder() );
t.commit();
s.close();
}
}

View File

@ -1,128 +0,0 @@
package org.hibernate.test.instrument.cases;
import org.junit.Assert;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.instrument.domain.Document;
import org.hibernate.test.instrument.domain.Folder;
import org.hibernate.test.instrument.domain.Owner;
/**
* @author Andrei Ivanov
*/
public class TestLazyBasicFieldAccessExecutable extends AbstractExecutable {
protected String[] getResources() {
return new String[] {"org/hibernate/test/instrument/domain/Documents.hbm.xml"};
}
public void execute() throws Exception {
Session s = getFactory().openSession();
Transaction t = s.beginTransaction();
Owner o = new Owner();
Document doc = new Document();
Folder fol = new Folder();
o.setName( "gavin" );
doc.setName( "Hibernate in Action" );
doc.setSummary( "blah" );
doc.updateText( "blah blah" );
fol.setName( "books" );
doc.setOwner( o );
doc.setFolder( fol );
fol.getDocuments().add( doc );
Assert.assertTrue( Hibernate.isPropertyInitialized( doc, "summary" ) );
s.persist( o );
s.persist( fol );
t.commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// update with lazy property initialized
doc.setName( "Doc Name" );
doc.setSummary( "u" );
s.update( doc );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// merge with lazy property initialized and updated
doc.setName( "Doc Name 1" );
doc.setSummary( "v" );
Document docManaged = (Document) s.merge( doc );
try {
Assert.assertEquals("v", docManaged.getSummary());
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
s.getTransaction().commit();
} catch (Exception e) {
s.getTransaction().rollback();
throw e;
} finally {
s.close();
}
s = getFactory().openSession();
s.getTransaction().begin();
// get the Document with an uninitialized summary
docManaged = (Document) s.get( Document.class, doc.getId() );
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
// merge with lazy property initialized in doc; uninitialized in docManaged.
doc.setSummary( "w" );
Assert.assertSame( docManaged, s.merge( doc ) );
Assert.assertEquals( "w", docManaged.getSummary() );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// get the Document with an uninitialized summary
docManaged = (Document) s.get( Document.class, doc.getId() );
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
// initialize docManaged.getSummary
Assert.assertEquals( "w", docManaged.getSummary() );
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
// merge with lazy property initialized in both doc and docManaged.
doc.setSummary( "x" );
Assert.assertSame( docManaged, s.merge( doc ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
Assert.assertEquals( "x", docManaged.getSummary() );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// get the Document with an uninitialized summary
Document docWithLazySummary = (Document) s.get( Document.class, doc.getId() );
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// summary should still be uninitialized.
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
docWithLazySummary.setName( "new name" );
// merge the Document with an uninitialized summary
docManaged = (Document) s.merge( docWithLazySummary );
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// get the Document with an uninitialized summary
docManaged = (Document) s.get( Document.class, doc.getId() );
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
// initialize docManaged.getSummary
Assert.assertEquals( "x", docManaged.getSummary() );
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
// merge the Document with an uninitialized summary
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
docManaged = (Document) s.merge( docWithLazySummary );
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
Assert.assertEquals( "x", docManaged.getSummary() );
s.getTransaction().commit();
s.close();
}
}

View File

@ -1,122 +0,0 @@
package org.hibernate.test.instrument.cases;
import org.junit.Assert;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.instrument.domain.Document;
import org.hibernate.test.instrument.domain.Folder;
import org.hibernate.test.instrument.domain.Owner;
/**
* @author Andrei Ivanov
*/
public class TestLazyBasicPropertyAccessExecutable extends AbstractExecutable {
protected String[] getResources() {
return new String[] {"org/hibernate/test/instrument/domain/DocumentsPropAccess.hbm.xml"};
}
public void execute() {
Session s = getFactory().openSession();
Transaction t = s.beginTransaction();
Owner o = new Owner();
Document doc = new Document();
Folder fol = new Folder();
o.setName( "gavin" );
doc.setName( "Hibernate in Action" );
doc.setSummary( "blah" );
doc.updateText( "blah blah" );
fol.setName( "books" );
doc.setOwner( o );
doc.setFolder( fol );
fol.getDocuments().add( doc );
Assert.assertTrue( Hibernate.isPropertyInitialized( doc, "summary" ) );
s.persist( o );
s.persist( fol );
t.commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// update with lazy property initialized
doc.setName( "Doc Name" );
doc.setSummary( "u" );
s.update( doc );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// merge with lazy property initialized and updated
doc.setName( "Doc Name 1" );
doc.setSummary( "v" );
Document docManaged = (Document) s.merge( doc );
Assert.assertEquals( "v", docManaged.getSummary() );
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// get the Document with an uninitialized summary
docManaged = (Document) s.get( Document.class, doc.getId() );
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
// merge with lazy property initialized in doc; uninitialized in docManaged.
doc.setSummary( "w" );
Assert.assertSame( docManaged, s.merge( doc ) );
Assert.assertEquals( "w", docManaged.getSummary() );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// get the Document with an uninitialized summary
docManaged = (Document) s.get( Document.class, doc.getId() );
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
// initialize docManaged.getSummary
Assert.assertEquals( "w", docManaged.getSummary() );
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
// merge with lazy property initialized in both doc and docManaged.
doc.setSummary( "x" );
Assert.assertSame( docManaged, s.merge( doc ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
Assert.assertEquals( "x", docManaged.getSummary() );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// get the Document with an uninitialized summary
Document docWithLazySummary = (Document) s.get( Document.class, doc.getId() );
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// summary should still be uninitialized.
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
docWithLazySummary.setName( "new name" );
// merge the Document with an uninitialized summary
docManaged = (Document) s.merge( docWithLazySummary );
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
s.getTransaction().commit();
s.close();
s = getFactory().openSession();
s.getTransaction().begin();
// get the Document with an uninitialized summary
docManaged = (Document) s.get( Document.class, doc.getId() );
Assert.assertFalse( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
// initialize docManaged.getSummary
Assert.assertEquals( "x", docManaged.getSummary() );
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
// merge the Document with an uninitialized summary
Assert.assertFalse( Hibernate.isPropertyInitialized( docWithLazySummary, "summary" ) );
docManaged = (Document) s.merge( docWithLazySummary );
Assert.assertTrue( Hibernate.isPropertyInitialized( docManaged, "summary" ) );
Assert.assertEquals( "x", docManaged.getSummary() );
s.getTransaction().commit();
s.close();
}
}

View File

@ -1,213 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import junit.framework.TestCase;
import org.hibernate.CacheMode;
import org.hibernate.Hibernate;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.test.instrument.domain.Document;
import org.hibernate.test.instrument.domain.Folder;
import org.hibernate.test.instrument.domain.Owner;
/**
* @author Steve Ebersole
*/
public class TestLazyExecutable extends AbstractExecutable {
public void execute() {
// The following block is repeated 100 times to reproduce HHH-2627.
// Without the fix, Oracle will run out of cursors using 10g with
// a default installation (ORA-01000: maximum open cursors exceeded).
// The number of loops may need to be adjusted depending on the how
// Oracle is configured.
// Note: The block is not indented to avoid a lot of irrelevant differences.
for ( int i=0; i<100; i++ ) {
SessionFactory factory = getFactory();
Session s = factory.openSession();
Transaction t = s.beginTransaction();
Owner o = new Owner();
Document doc = new Document();
Folder fol = new Folder();
o.setName("gavin");
doc.setName("Hibernate in Action");
doc.setSummary("blah");
doc.updateText("blah blah");
fol.setName("books");
doc.setOwner(o);
doc.setFolder(fol);
fol.getDocuments().add(doc);
s.save(o);
s.save(fol);
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = ( Document ) s.get( Document.class, doc.getId() );
TestCase.assertTrue( Hibernate.isPropertyInitialized(doc, "weirdProperty"));
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "name"));
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "text"));
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "upperCaseName"));
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "folder"));
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "owner"));
doc.getUpperCaseName(); // should force initialization
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "text"));
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "weirdProperty"));
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "upperCaseName"));
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "folder"));
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "owner"));
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = (Document) s.createQuery("from Document").uniqueResult();
doc.getName();
TestCase.assertEquals( doc.getText(), "blah blah" );
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = (Document) s.createQuery("from Document").uniqueResult();
doc.getName();
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "text"));
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "summary"));
TestCase.assertEquals( doc.getText(), "blah blah" );
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "text"));
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "summary"));
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = (Document) s.createQuery("from Document").uniqueResult();
doc.setName("HiA");
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = (Document) s.createQuery("from Document").uniqueResult();
TestCase.assertEquals( doc.getName(), "HiA" );
TestCase.assertEquals( doc.getText(), "blah blah" );
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = (Document) s.createQuery("from Document").uniqueResult();
doc.getText();
doc.setName("HiA second edition");
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = (Document) s.createQuery("from Document").uniqueResult();
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "weirdProperty"));
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "name"));
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "text"));
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "upperCaseName"));
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "owner"));
TestCase.assertEquals( doc.getName(), "HiA second edition" );
TestCase.assertEquals( doc.getText(), "blah blah" );
TestCase.assertEquals( doc.getUpperCaseName(), "HIA SECOND EDITION" );
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "text"));
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "weirdProperty"));
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "upperCaseName"));
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = (Document) s.createQuery("from Document").uniqueResult();
t.commit();
s.close();
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "text"));
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
s.lock(doc, LockMode.NONE);
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "text"));
TestCase.assertEquals( doc.getText(), "blah blah" );
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "text"));
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = (Document) s.createQuery("from Document").uniqueResult();
t.commit();
s.close();
doc.setName("HiA2");
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "text"));
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
s.saveOrUpdate(doc);
s.flush();
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "text"));
TestCase.assertEquals( doc.getText(), "blah blah" );
TestCase.assertTrue(Hibernate.isPropertyInitialized(doc, "text"));
doc.updateText("blah blah blah blah");
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = ( Document ) s.createQuery("from Document").uniqueResult();
TestCase.assertEquals( doc.getName(), "HiA2" );
TestCase.assertEquals( doc.getText(), "blah blah blah blah" );
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = (Document) s.load( Document.class, doc.getId() );
doc.getName();
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "text"));
TestCase.assertFalse(Hibernate.isPropertyInitialized(doc, "summary"));
t.commit();
s.close();
s = factory.openSession();
s.setCacheMode( CacheMode.IGNORE );
t = s.beginTransaction();
doc = (Document) s.createQuery("from Document").uniqueResult();
//s.delete(doc);
s.delete( doc.getFolder() );
s.delete( doc.getOwner() );
s.flush();
t.commit();
s.close();
}
}
}

View File

@ -1,79 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import junit.framework.Assert;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.instrument.domain.Document;
import org.hibernate.test.instrument.domain.Folder;
import org.hibernate.test.instrument.domain.Owner;
/**
* @author Steve Ebersole
*/
public class TestLazyManyToOneExecutable extends AbstractExecutable {
public void execute() {
Session s = getFactory().openSession();
Transaction t = s.beginTransaction();
Owner gavin = new Owner();
Document hia = new Document();
Folder fol = new Folder();
gavin.setName("gavin");
hia.setName("Hibernate in Action");
hia.setSummary("blah");
hia.updateText("blah blah");
fol.setName("books");
hia.setOwner(gavin);
hia.setFolder(fol);
fol.getDocuments().add(hia);
s.persist(gavin);
s.persist(fol);
t.commit();
s.close();
s = getFactory().openSession();
t = s.beginTransaction();
hia = (Document) s.createCriteria(Document.class).uniqueResult();
Assert.assertEquals( hia.getFolder().getClass(), Folder.class);
fol = hia.getFolder();
Assert.assertTrue( Hibernate.isInitialized(fol) );
t.commit();
s.close();
s = getFactory().openSession();
t = s.beginTransaction();
hia = (Document) s.createCriteria(Document.class).uniqueResult();
Assert.assertSame( hia.getFolder(), s.load(Folder.class, fol.getId()) );
Assert.assertTrue( Hibernate.isInitialized( hia.getFolder() ) );
t.commit();
s.close();
s = getFactory().openSession();
t = s.beginTransaction();
fol = (Folder) s.get(Folder.class, fol.getId());
hia = (Document) s.createCriteria(Document.class).uniqueResult();
Assert.assertSame( fol, hia.getFolder() );
fol = hia.getFolder();
Assert.assertTrue( Hibernate.isInitialized(fol) );
t.commit();
s.close();
s = getFactory().openSession();
t = s.beginTransaction();
fol = (Folder) s.load(Folder.class, fol.getId());
hia = (Document) s.createCriteria(Document.class).uniqueResult();
Assert.assertNotSame( fol, hia.getFolder() );
fol = hia.getFolder();
Assert.assertTrue( Hibernate.isInitialized(fol) );
s.delete(hia.getFolder());
s.delete(hia.getOwner());
t.commit();
s.close();
}
}

View File

@ -1,98 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import java.util.Iterator;
import org.hibernate.Session;
import org.hibernate.bytecode.instrumentation.internal.FieldInterceptionHelper;
import org.hibernate.test.instrument.domain.Problematic;
import junit.framework.Assert;
/**
* {@inheritDoc}
*
* @author Steve Ebersole
*/
public class TestLazyPropertyCustomTypeExecutable extends AbstractExecutable {
protected String[] getResources() {
return new String[] { "org/hibernate/test/instrument/domain/Problematic.hbm.xml" };
}
public void execute() throws Exception {
Session s = getFactory().openSession();
Problematic p = new Problematic();
try {
s.beginTransaction();
p.setName( "whatever" );
p.setBytes( new byte[] { 1, 0, 1, 1, 0 } );
s.save( p );
s.getTransaction().commit();
} catch (Exception e) {
s.getTransaction().rollback();
throw e;
} finally {
s.close();
}
// this access should be ok because p1 is not a lazy proxy
s = getFactory().openSession();
try {
s.beginTransaction();
Problematic p1 = (Problematic) s.get( Problematic.class, p.getId() );
Assert.assertTrue( FieldInterceptionHelper.isInstrumented( p1 ) );
p1.getRepresentation();
s.getTransaction().commit();
} catch (Exception e) {
s.getTransaction().rollback();
throw e;
} finally {
s.close();
}
s = getFactory().openSession();
try {
s.beginTransaction();
Problematic p1 = (Problematic) s.createQuery( "from Problematic" ).setReadOnly(true ).list().get( 0 );
p1.getRepresentation();
s.getTransaction().commit();
} catch (Exception e) {
s.getTransaction().rollback();
throw e;
} finally {
s.close();
}
s = getFactory().openSession();
try {
s.beginTransaction();
Problematic p1 = (Problematic) s.load( Problematic.class, p.getId() );
Assert.assertFalse( FieldInterceptionHelper.isInstrumented( p1 ) );
p1.setRepresentation( p.getRepresentation() );
s.getTransaction().commit();
} catch (Exception e) {
s.getTransaction().rollback();
throw e;
} finally {
s.close();
}
}
protected void cleanup() {
Session s = getFactory().openSession();
s.beginTransaction();
Iterator itr = s.createQuery( "from Problematic" ).list().iterator();
while ( itr.hasNext() ) {
Problematic p = (Problematic) itr.next();
s.delete( p );
}
s.getTransaction().commit();
s.close();
}
}

View File

@ -1,73 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import junit.framework.Assert;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.instrument.domain.Entity;
/**
*
* @author Steve Ebersole
*/
public class TestManyToOneProxyExecutable extends AbstractExecutable {
public void execute() {
Session s = getFactory().openSession();
Transaction t = s.beginTransaction();
Entity root = new Entity( "root" );
Entity child1 = new Entity( "child1" );
Entity child2 = new Entity( "child2" );
root.setChild( child1 );
child1.setSibling( child2 );
Entity gChild1 = new Entity( "grandchild 1" );
Entity gChild2 = new Entity( "grandchild 2" );
child1.setChild( gChild1 );
gChild1.setSibling( gChild2 );
s.save( root );
t.commit();
s.close();
// NOTE : child is mapped with lazy="proxy"; sibling with lazy="no-proxy"...
s = getFactory().openSession();
t = s.beginTransaction();
// load root
root = ( Entity ) s.get( Entity.class, root.getId() );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "name" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "sibling" ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( root, "child" ) );
// get a handle to the child1 proxy reference (and make certain that
// this does not force the lazy properties of the root entity
// to get initialized.
child1 = root.getChild();
Assert.assertFalse( Hibernate.isInitialized( child1 ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "name" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "sibling" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( child1, "name" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( child1, "sibling" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( child1, "child" ) );
child1.getName();
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "name" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "sibling" ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( child1, "name" ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( child1, "sibling" ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( child1, "child" ) );
gChild1 = child1.getChild();
Assert.assertFalse( Hibernate.isInitialized( gChild1 ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "name" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "sibling" ) );
s.delete( root );
t.commit();
s.close();
}
}

View File

@ -1,75 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.cases;
import junit.framework.Assert;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.instrument.domain.EntityWithOneToOnes;
import org.hibernate.test.instrument.domain.OneToOneNoProxy;
import org.hibernate.test.instrument.domain.OneToOneProxy;
/**
*
* @author Gail Badner
*/
public class TestSharedPKOneToOneExecutable extends AbstractExecutable {
protected String[] getResources() {
return new String[] {"org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml"};
}
public void execute() {
Session s = getFactory().openSession();
Transaction t = s.beginTransaction();
EntityWithOneToOnes root = new EntityWithOneToOnes( "root" );
OneToOneProxy oneToOneProxy = new OneToOneProxy( "oneToOneProxy" );
root.setOneToOneProxy( oneToOneProxy );
oneToOneProxy.setEntity( root );
OneToOneNoProxy oneToOneNoProxy = new OneToOneNoProxy( "oneToOneNoProxy" );
root.setOneToOneNoProxy( oneToOneNoProxy );
oneToOneNoProxy.setEntity( root );
s.save( root );
t.commit();
s.close();
// NOTE : oneToOneProxy is mapped with lazy="proxy"; oneToOneNoProxy with lazy="no-proxy"...
s = getFactory().openSession();
t = s.beginTransaction();
// load root
root = ( EntityWithOneToOnes ) s.load( EntityWithOneToOnes.class, root.getId() );
Assert.assertFalse( Hibernate.isInitialized( root ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "name" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneProxy" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
root.getName();
Assert.assertTrue( Hibernate.isInitialized( root ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( root, "name" ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( root, "oneToOneProxy" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
// get a handle to the oneToOneProxy proxy reference (and make certain that
// this does not force the lazy properties of the root entity
// to get initialized.
root.getOneToOneProxy();
Assert.assertTrue( Hibernate.isInitialized( oneToOneProxy ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( root.getOneToOneProxy(), "name" ) );
Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
root.getOneToOneNoProxy();
Assert.assertTrue( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
Assert.assertTrue( Hibernate.isPropertyInitialized( root.getOneToOneNoProxy(), "name") );
s.delete( root );
t.commit();
s.close();
}
}

View File

@ -1,116 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.domain;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Arrays;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.usertype.UserType;
/**
* A simple byte[]-based custom type.
*/
public class CustomBlobType implements UserType {
/**
* {@inheritDoc}
*/
public Object nullSafeGet(ResultSet rs, String names[], SessionImplementor session, Object owner) throws SQLException {
// cast just to make sure...
return StandardBasicTypes.BINARY.nullSafeGet( rs, names[0], session );
}
/**
* {@inheritDoc}
*/
public void nullSafeSet(PreparedStatement ps, Object value, int index, SessionImplementor session) throws SQLException, HibernateException {
// cast just to make sure...
StandardBasicTypes.BINARY.nullSafeSet( ps, value, index, session );
}
/**
* {@inheritDoc}
*/
public Object deepCopy(Object value) {
byte result[] = null;
if ( value != null ) {
byte bytes[] = ( byte[] ) value;
result = new byte[bytes.length];
System.arraycopy( bytes, 0, result, 0, bytes.length );
}
return result;
}
/**
* {@inheritDoc}
*/
public boolean isMutable() {
return true;
}
/**
* {@inheritDoc}
*/
public int[] sqlTypes() {
return new int[] { Types.VARBINARY };
}
/**
* {@inheritDoc}
*/
public Class returnedClass() {
return byte[].class;
}
/**
* {@inheritDoc}
*/
public boolean equals(Object x, Object y) {
return Arrays.equals( ( byte[] ) x, ( byte[] ) y );
}
/**
* {@inheritDoc}
*/
public Object assemble(Serializable arg0, Object arg1)
throws HibernateException {
return null;
}
/**
* {@inheritDoc}
*/
public Serializable disassemble(Object arg0)
throws HibernateException {
return null;
}
/**
* {@inheritDoc}
*/
public int hashCode(Object arg0)
throws HibernateException {
return 0;
}
/**
* {@inheritDoc}
*/
public Object replace(Object arg0, Object arg1, Object arg2)
throws HibernateException {
return null;
}
}

View File

@ -1,129 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id: Document.java 9538 2006-03-04 00:17:57Z steve.ebersole@jboss.com $
package org.hibernate.test.instrument.domain;
import java.util.Date;
/**
* @author Gavin King
*/
public class Document {
private Long id;
private String name;
private String upperCaseName;
private String summary;
private String text;
private Owner owner;
private Folder folder;
private double sizeKb;
private Date lastTextModification = new Date();
/**
* @return Returns the folder.
*/
public Folder getFolder() {
return folder;
}
/**
* @param folder The folder to set.
*/
public void setFolder(Folder folder) {
this.folder = folder;
}
/**
* @return Returns the owner.
*/
public Owner getOwner() {
return owner;
}
/**
* @param owner The owner to set.
*/
public void setOwner(Owner owner) {
this.owner = owner;
}
/**
* @return Returns the id.
*/
public Long getId() {
return id;
}
/**
* @param id The id to set.
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return Returns the name.
*/
public String getName() {
return name;
}
/**
* @param name The name to set.
*/
public void setName(String name) {
this.name = name;
}
/**
* @return Returns the summary.
*/
public String getSummary() {
return summary;
}
/**
* @param summary The summary to set.
*/
public void setSummary(String summary) {
this.summary = summary;
}
/**
* @return Returns the text.
*/
public String getText() {
return text;
}
/**
* @param text The text to set.
*/
private void setText(String text) {
this.text = text;
}
/**
* @return Returns the upperCaseName.
*/
public String getUpperCaseName() {
return upperCaseName;
}
/**
* @param upperCaseName The upperCaseName to set.
*/
public void setUpperCaseName(String upperCaseName) {
this.upperCaseName = upperCaseName;
}
/**
* @param sizeKb The size in KBs.
*/
public void setSizeKb(double sizeKb) {
this.sizeKb = sizeKb;
}
/**
* @return The size in KBs.
*/
public double getSizeKb() {
return sizeKb;
}
public void updateText(String newText) {
if ( !newText.equals(text) ) {
this.text = newText;
lastTextModification = new Date();
}
}
}

View File

@ -1,78 +0,0 @@
<?xml version="1.0"?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
This mapping demonstrates
(1) use of lazy properties - this feature requires buildtime
bytecode instrumentation; we don't think this is a very
necessary feature, but provide it for completeleness; if
Hibernate encounters uninstrumented classes, lazy property
fetching will be silently disabled, to enable testing
(2) use of a formula to define a "derived property"
-->
<hibernate-mapping package="org.hibernate.test.instrument.domain" default-access="field">
<class name="Folder" table="folders">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true" length="50"/>
<many-to-one name="parent"/>
<bag name="subfolders" inverse="true" cascade="save-update">
<key column="parent"/>
<one-to-many class="Folder"/>
</bag>
<bag name="documents" inverse="true" cascade="all-delete-orphan">
<key column="folder"/>
<one-to-many class="Document"/>
</bag>
</class>
<class name="Owner" table="owners" lazy="false">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true" length="50"/>
</class>
<class name="Document" table="documents">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true" length="50"/>
<property name="upperCaseName" formula="upper(name)" lazy="true"/>
<property name="summary" column="`summary`" not-null="true" length="200" lazy="true"/>
<many-to-one name="folder" not-null="true" lazy="no-proxy"/>
<many-to-one name="owner" not-null="true" lazy="no-proxy" fetch="select"/>
<property name="text" not-null="true" length="2000" lazy="true"/>
<property name="lastTextModification" not-null="true" lazy="true" access="field"/>
<property name="sizeKb" lazy="true">
<column name="size_mb"
read="size_mb * 1024.0"
write="? / cast( 1024.0 as float )"/>
</property>
</class>
<class name="Entity" table="entity">
<id name="id" column="ID" type="long">
<generator class="increment"/>
</id>
<property name="name" column="NAME" type="string" lazy="true"/>
<many-to-one name="child" column="PRNT_ID" class="Entity" lazy="proxy" cascade="all" />
<many-to-one name="sibling" column="RIGHT_ID" class="Entity" lazy="no-proxy" cascade="all" />
</class>
</hibernate-mapping>

View File

@ -1,78 +0,0 @@
<?xml version="1.0"?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
This mapping demonstrates
(1) use of lazy properties - this feature requires buildtime
bytecode instrumentation; we don't think this is a very
necessary feature, but provide it for completeleness; if
Hibernate encounters uninstrumented classes, lazy property
fetching will be silently disabled, to enable testing
(2) use of a formula to define a "derived property"
-->
<hibernate-mapping package="org.hibernate.test.instrument.domain" default-access="property">
<class name="Folder" table="folders">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true" length="50"/>
<many-to-one name="parent"/>
<bag name="subfolders" inverse="true" cascade="save-update">
<key column="parent"/>
<one-to-many class="Folder"/>
</bag>
<bag name="documents" inverse="true" cascade="all-delete-orphan">
<key column="folder"/>
<one-to-many class="Document"/>
</bag>
</class>
<class name="Owner" table="owners" lazy="false">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true" length="50"/>
</class>
<class name="Document" table="documents">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true" length="50"/>
<property name="upperCaseName" formula="upper(name)" lazy="true"/>
<property name="summary" column="`summary`" not-null="true" length="200" lazy="true"/>
<many-to-one name="folder" not-null="true" lazy="no-proxy"/>
<many-to-one name="owner" not-null="true" lazy="no-proxy" fetch="select"/>
<property name="text" not-null="true" length="2000" lazy="true"/>
<property name="lastTextModification" not-null="true" lazy="true" access="field"/>
<property name="sizeKb" lazy="true">
<column name="size_mb"
read="size_mb * 1024.0"
write="? / cast( 1024.0 as float )"/>
</property>
</class>
<class name="Entity" table="entity">
<id name="id" column="ID" type="long">
<generator class="increment"/>
</id>
<property name="name" column="NAME" type="string" lazy="true"/>
<many-to-one name="child" column="PRNT_ID" class="Entity" lazy="proxy" cascade="all" />
<many-to-one name="sibling" column="RIGHT_ID" class="Entity" lazy="no-proxy" cascade="all" />
</class>
</hibernate-mapping>

View File

@ -1,59 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.domain;
/**
* todo: describe Entity
*
* @author Steve Ebersole
*/
public class Entity {
private Long id;
private String name;
private Entity child;
private Entity sibling;
public Entity() {
}
public Entity(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Entity getChild() {
return child;
}
public void setChild(Entity child) {
this.child = child;
}
public Entity getSibling() {
return sibling;
}
public void setSibling(Entity sibling) {
this.sibling = sibling;
}
}

View File

@ -1,57 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.instrument.domain;
/**
* @author Gail Badner
*/
public class EntityWithOneToOnes {
private Long id;
private String name;
private OneToOneNoProxy oneToOneNoProxy;
private OneToOneProxy oneToOneProxy;
public EntityWithOneToOnes() {
}
public EntityWithOneToOnes(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public OneToOneNoProxy getOneToOneNoProxy() {
return oneToOneNoProxy;
}
public void setOneToOneNoProxy(OneToOneNoProxy oneToOneNoProxy) {
this.oneToOneNoProxy = oneToOneNoProxy;
}
public OneToOneProxy getOneToOneProxy() {
return oneToOneProxy;
}
public void setOneToOneProxy(OneToOneProxy oneToOneProxy) {
this.oneToOneProxy = oneToOneProxy;
}
}

View File

@ -1,86 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
//$Id: Folder.java 9538 2006-03-04 00:17:57Z steve.ebersole@jboss.com $
package org.hibernate.test.instrument.domain;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author Gavin King
*/
public class Folder {
private Long id;
private String name;
private Folder parent;
private Collection subfolders = new ArrayList();
private Collection documents = new ArrayList();
public boolean nameWasread;
/**
* @return Returns the id.
*/
public Long getId() {
return id;
}
/**
* @param id The id to set.
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return Returns the name.
*/
public String getName() {
nameWasread = true;
return name;
}
/**
* @param name The name to set.
*/
public void setName(String name) {
this.name = name;
}
/**
* @return Returns the documents.
*/
public Collection getDocuments() {
return documents;
}
/**
* @param documents The documents to set.
*/
public void setDocuments(Collection documents) {
this.documents = documents;
}
/**
* @return Returns the parent.
*/
public Folder getParent() {
return parent;
}
/**
* @param parent The parent to set.
*/
public void setParent(Folder parent) {
this.parent = parent;
}
/**
* @return Returns the subfolders.
*/
public Collection getSubfolders() {
return subfolders;
}
/**
* @param subfolders The subfolders to set.
*/
public void setSubfolders(Collection subfolders) {
this.subfolders = subfolders;
}
}

Some files were not shown because too many files have changed in this diff Show More