Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.bytecode.enhance.internal.bytebuddy;

import java.lang.reflect.Member;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class BridgeMembersClassInfo {
private final Class<?> clazz;
private final List<String> propertyNames = new ArrayList<>();
private final List<Member> getters = new ArrayList<>();
private final List<Member> setters = new ArrayList<>();

public BridgeMembersClassInfo(Class<?> clazz) {
this.clazz = Objects.requireNonNull(clazz);
}

public Class<?> getClazz() {
return clazz;
}

public Iterable<Member> gettersIterable() {
return getters;
}

public Iterable<Member> settersIterable() {
return setters;
}

public boolean containsGetter(Member getter) {
return getters.contains( getter );
}

public boolean containsSetter(Member setter) {
return setters.contains( setter );
}

public void addGetter(Member getter) {
getters.add( getter );
}

public void addSetter(Member setter) {
setters.add( setter );
}

public void addProperty(String propertyName) {
propertyNames.add( propertyName );
}

public boolean propertyNamesIsEmpty() {
return propertyNames.isEmpty();
}

public String encodeName() {
return NameEncodeHelper.encodeName(
propertyNames.toArray( new String[0] ),
getters.toArray( new Member[0] ),
setters.toArray( new Member[0] )
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ class ByteBuddyEnhancementContext {
private static final ElementMatcher.Junction<MethodDescription> IS_GETTER = isGetter();

private final EnhancementContext enhancementContext;
private final EnhancerImplConstants constants;

private final ConcurrentHashMap<TypeDescription, Map<String, MethodDescription>> getterByTypeMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Object> locksMap = new ConcurrentHashMap<>();

ByteBuddyEnhancementContext(final EnhancementContext enhancementContext) {
ByteBuddyEnhancementContext(final EnhancementContext enhancementContext, EnhancerImplConstants enhancerConstants) {
this.enhancementContext = Objects.requireNonNull( enhancementContext );
this.constants = enhancerConstants;
}

public boolean isEntityClass(TypeDescription classDescriptor) {
Expand Down Expand Up @@ -122,7 +124,8 @@ else if ( isMappedSuperclassClass( managedCtClass ) ) {
final EnhancerImpl.AnnotatedFieldDescription[] enhancedFields = PersistentAttributeTransformer.collectPersistentFields(
managedCtClass,
this,
typePool
typePool,
constants
)
.getEnhancedFields();
for ( EnhancerImpl.AnnotatedFieldDescription enhancedField : enhancedFields ) {
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

import jakarta.persistence.Transient;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.modifier.FieldPersistence;
import net.bytebuddy.description.modifier.ModifierContributor;
import net.bytebuddy.description.modifier.Visibility;
Expand All @@ -16,13 +18,33 @@
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.StubMethod;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import net.bytebuddy.jar.asm.Type;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import org.hibernate.bytecode.enhance.internal.tracker.CompositeOwnerTracker;
import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker;
import org.hibernate.bytecode.enhance.spi.CollectionTracker;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.engine.spi.CompositeOwner;
import org.hibernate.engine.spi.CompositeTracker;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.ExtendedSelfDirtinessTracker;
import org.hibernate.engine.spi.ManagedComposite;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.ManagedMappedSuperclass;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.proxy.ProxyConfiguration;

import static net.bytebuddy.matcher.ElementMatchers.isDefaultFinalizer;

/**
* Extracts constants used by EnhancerImpl.
Expand Down Expand Up @@ -51,8 +73,9 @@ public final class EnhancerImplConstants {
final Implementation implementationSetPersistenceInfo;

//Frequently used Modifiers:
final int methodModifierPUBLIC = ModifierContributor.Resolver.of( List.of( Visibility.PUBLIC ) ).resolve();
final int fieldModifierPRIVATE_TRANSIENT = ModifierContributor.Resolver.of( List.of( FieldPersistence.TRANSIENT, Visibility.PRIVATE ) ).resolve();
final int modifierPUBLIC = ModifierContributor.Resolver.of( List.of( Visibility.PUBLIC ) ).resolve();
public final int modifierPRIVATE = ModifierContributor.Resolver.of( List.of( Visibility.PRIVATE ) ).resolve();
final int modifierPRIVATE_TRANSIENT = ModifierContributor.Resolver.of( List.of( FieldPersistence.TRANSIENT, Visibility.PRIVATE ) ).resolve();

//Frequently used annotations, declared as collections as otherwise they get wrapped into them over and over again:
final Collection<? extends AnnotationDescription> TRANSIENT_ANNOTATION = List.of(
Expand All @@ -62,12 +85,94 @@ public final class EnhancerImplConstants {
final TypeDefinition TypeVoid = TypeDescription.ForLoadedType.of( void.class );
final TypeDefinition TypeBooleanPrimitive = TypeDescription.ForLoadedType.of( boolean.class );
final TypeDefinition TypeIntegerPrimitive = TypeDescription.ForLoadedType.of( int.class );
public final TypeDefinition TypeProxyConfiguration_Interceptor = TypeDescription.ForLoadedType.of( ProxyConfiguration.Interceptor.class );
final TypeDefinition TypeManagedEntity = TypeDescription.ForLoadedType.of( ManagedEntity.class );
final TypeDefinition TypeEntityEntry = TypeDescription.ForLoadedType.of( EntityEntry.class );
final TypeDefinition TypePersistentAttributeInterceptor = TypeDescription.ForLoadedType.of( PersistentAttributeInterceptor.class );
final TypeDefinition TypeObject = TypeDescription.ForLoadedType.of( Object.class );
public final TypeDefinition TypeObject = TypeDescription.ForLoadedType.of( Object.class );
final TypeDefinition TypeString = TypeDescription.ForLoadedType.of( String.class );
final TypeDefinition Type_Array_String = TypeDescription.ForLoadedType.of( String[].class );
final TypeDefinition TypeCollectionTracker = TypeDescription.ForLoadedType.of( CollectionTracker.class );
final TypeDefinition Type_Array_Object = TypeDescription.ForLoadedType.of( Object[].class );
final TypeDefinition TypeLazyAttributeLoadingInterceptor = TypeDescription.ForLoadedType.of(
LazyAttributeLoadingInterceptor.class );
final TypeDefinition TypeCompositeOwnerTracker = TypeDescription.ForLoadedType.of( CompositeOwnerTracker.class );
public final TypeDefinition TypeInstantiationOptimizer = TypeDescription.ForLoadedType.of(
ReflectionOptimizer.InstantiationOptimizer.class );

//Careful with the following types being used: the ByteBuddy receiver often supports overloading, and using
//one of the other specific types in the declaration might lead to unexpectedly invoking a different method.
final List<TypeDefinition> INTERFACES_for_PersistentAttributeInterceptor = List.of( TypePersistentAttributeInterceptor );
public final Collection<? extends TypeDefinition> INTERFACES_for_AccessOptimizer = List.of(
TypeDescription.ForLoadedType.of( ReflectionOptimizer.AccessOptimizer.class )
);
public final Collection<? extends TypeDefinition> INTERFACES_for_SelfDirtinessTracker = List.of(
TypeDescription.ForLoadedType.of( SelfDirtinessTracker.class )
);
public final Collection<? extends TypeDefinition> INTERFACES_for_ExtendedSelfDirtinessTracker = List.of(
TypeDescription.ForLoadedType.of( ExtendedSelfDirtinessTracker.class )
);
public final Collection<? extends TypeDefinition> INTERFACES_for_ManagedComposite = List.of(
TypeDescription.ForLoadedType.of( ManagedComposite.class )
);
public final Collection<? extends TypeDefinition> INTERFACES_for_ManagedMappedSuperclass = List.of(
TypeDescription.ForLoadedType.of( ManagedMappedSuperclass.class )
);
public final Collection<? extends TypeDefinition> INTERFACES_for_CompositeOwner = List.of(
TypeDescription.ForLoadedType.of( CompositeOwner.class )
);
public final Collection<? extends TypeDefinition> INTERFACES_for_CompositeTracker = List.of(
TypeDescription.ForLoadedType.of( CompositeTracker.class )
);
public final Collection<? extends TypeDefinition> INTERFACES_for_PersistentAttributeInterceptable = List.of(
TypeDescription.ForLoadedType.of( PersistentAttributeInterceptable.class )
);
public final Collection<? extends TypeDefinition> INTERFACES_for_ProxyConfiguration = List.of(
TypeDescription.ForLoadedType.of( ProxyConfiguration.class )
);
public final Collection<? extends TypeDefinition> INTERFACES_for_ManagedEntity = List.of( TypeManagedEntity );

//Frequently used ElementMatchers:
final ElementMatcher.Junction<MethodDescription> DEFAULT_FINALIZER = isDefaultFinalizer();
public final ElementMatcher.Junction<NamedElement> newInstanceMethodName = ElementMatchers.named( "newInstance" );
public final ElementMatcher.Junction<NamedElement> getPropertyValuesMethodName = ElementMatchers.named( "getPropertyValues" );
public final ElementMatcher.Junction<NamedElement> setPropertyValuesMethodName = ElementMatchers.named( "setPropertyValues" );
public final ElementMatcher.Junction<NamedElement> getPropertyNamesMethodName = ElementMatchers.named( "getPropertyNames" );

//Frequently used types for field definitions:
final TypeDescription.Generic DirtyTrackerTypeDescription = TypeDefinition.Sort.describe( DirtyTracker.class );

//Internal names:
final String internalName_CompositeTracker = Type.getInternalName( CompositeTracker.class );
final String internalName_LazyPropertyInitializer = Type.getInternalName( LazyPropertyInitializer.class );
final String internalName_Object = Type.getInternalName( Object.class );
final String internalName_String = Type.getInternalName( String.class );
final String internalName_BytecodeLazyAttributeInterceptor = Type.getInternalName( BytecodeLazyAttributeInterceptor.class );
final String internalName_LazyAttributeLoadingInterceptor = Type.getInternalName(
LazyAttributeLoadingInterceptor.class );
final String internalName_PersistentAttributeInterceptor = Type.getInternalName(
PersistentAttributeInterceptor.class );

//Method Descriptors:
final String methodDescriptor_SetOwner = Type.getMethodDescriptor(
Type.getType( void.class ),
Type.getType( String.class ),
Type.getType( CompositeOwner.class )
);
final String methodDescriptor_getInterceptor = Type.getMethodDescriptor(
Type.getType( PersistentAttributeInterceptor.class )
);
final String methodDescriptor_attributeInitialized = Type.getMethodDescriptor(
Type.getType( void.class ),
Type.getType( String.class )
);
final String methodDescriptor_isAttributeLoaded = Type.getMethodDescriptor(
Type.getType( boolean.class ),
Type.getType( String.class )
);

//Others :
final String Serializable_TYPE_DESCRIPTOR = Type.getDescriptor( Serializable.class );

public EnhancerImplConstants() {
this.adviceLocator = ClassFileLocator.ForClassLoader.of( CodeTemplates.class.getClassLoader() );
Expand Down Expand Up @@ -110,4 +215,8 @@ public EnhancerImplConstants() {
.wrap( StubMethod.INSTANCE );
}

public ElementMatcher<? super MethodDescription> defaultFinalizer() {
return DEFAULT_FINALIZER;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.AnnotatedFieldDescription;
import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;

import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.description.field.FieldDescription;
Expand All @@ -29,18 +28,21 @@ abstract class FieldReaderAppender implements ByteCodeAppender {

protected final FieldDescription.InDefinedShape persistentFieldAsDefined;

private FieldReaderAppender(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
protected final EnhancerImplConstants constants;

private FieldReaderAppender(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField, EnhancerImplConstants constants) {
this.managedCtClass = managedCtClass;
this.persistentField = persistentField;
this.persistentFieldAsDefined = persistentField.asDefined();
this.constants = constants;
}

static ByteCodeAppender of(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
static ByteCodeAppender of(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField, EnhancerImplConstants constants) {
if ( !persistentField.isVisibleTo( managedCtClass ) ) {
return new MethodDispatching( managedCtClass, persistentField );
return new MethodDispatching( managedCtClass, persistentField, constants );
}
else {
return new FieldWriting( managedCtClass, persistentField );
return new FieldWriting( managedCtClass, persistentField, constants );
}
}

Expand All @@ -63,7 +65,7 @@ public Size apply(
Opcodes.INVOKEVIRTUAL,
managedCtClass.getInternalName(),
EnhancerConstants.INTERCEPTOR_GETTER_NAME,
Type.getMethodDescriptor( Type.getType( PersistentAttributeInterceptor.class ) ),
constants.methodDescriptor_getInterceptor,
false
);
Label skip = new Label();
Expand All @@ -76,7 +78,7 @@ public Size apply(
Opcodes.INVOKEVIRTUAL,
managedCtClass.getInternalName(),
EnhancerConstants.INTERCEPTOR_GETTER_NAME,
Type.getMethodDescriptor( Type.getType( PersistentAttributeInterceptor.class ) ),
constants.methodDescriptor_getInterceptor,
false
);
// .readXXX( self, fieldName, field );
Expand All @@ -87,7 +89,7 @@ public Size apply(
fieldRead( methodVisitor );
methodVisitor.visitMethodInsn(
Opcodes.INVOKEINTERFACE,
Type.getInternalName( PersistentAttributeInterceptor.class ),
constants.internalName_PersistentAttributeInterceptor,
"read" + EnhancerImpl.capitalize( dispatcherType.getSimpleName() ),
Type.getMethodDescriptor(
Type.getType( dispatcherType.getDescriptor() ),
Expand Down Expand Up @@ -127,8 +129,8 @@ public Size apply(

private static class FieldWriting extends FieldReaderAppender {

private FieldWriting(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
super( managedCtClass, persistentField );
private FieldWriting(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField, EnhancerImplConstants constants) {
super( managedCtClass, persistentField, constants );
}

@Override
Expand All @@ -154,8 +156,8 @@ protected void fieldWrite(MethodVisitor methodVisitor) {

private static class MethodDispatching extends FieldReaderAppender {

private MethodDispatching(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField) {
super( managedCtClass, persistentField );
private MethodDispatching(TypeDescription managedCtClass, AnnotatedFieldDescription persistentField, EnhancerImplConstants constants) {
super( managedCtClass, persistentField, constants );
}

@Override
Expand Down
Loading