Skip to content

Commit 2753116

Browse files
committed
#136 - Allow control over whether to track implementors
1 parent a7d188f commit 2753116

File tree

20 files changed

+473
-184
lines changed

20 files changed

+473
-184
lines changed

buildSrc/src/main/groovy/testing.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ dependencies {
1212
testImplementation jakartaLibs.jpa
1313
testImplementation testLibs.junit5Api
1414
testImplementation testLibs.assertjCore
15+
testImplementation testLibs.junit5Params
1516

1617
testImplementation testLibs.junit5Engine
1718
testImplementation testLibs.log4j

hibernate-models-bytebuddy/src/main/java/org/hibernate/models/bytebuddy/internal/ByteBuddyContextProvider.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.hibernate.models.bytebuddy.Settings;
1010
import org.hibernate.models.internal.BasicModelsContextImpl;
1111
import org.hibernate.models.spi.ClassLoading;
12+
import org.hibernate.models.spi.ModelsConfiguration;
1213
import org.hibernate.models.spi.ModelsContext;
1314
import org.hibernate.models.spi.RegistryPrimer;
1415
import org.hibernate.models.spi.ModelsContextProvider;
@@ -27,12 +28,13 @@ public ModelsContext produceContext(
2728
RegistryPrimer registryPrimer,
2829
Map<Object, Object> configProperties) {
2930
final TypePool typePool = resolveTypePool( configProperties );
31+
final boolean trackImplementors = ModelsConfiguration.shouldTrackImplementors( configProperties );
3032

3133
if ( typePool != null ) {
32-
return new ByteBuddyModelsContextImpl( typePool, classLoading, registryPrimer );
34+
return new ByteBuddyModelsContextImpl( typePool, trackImplementors, classLoading, registryPrimer );
3335
}
3436

35-
return new BasicModelsContextImpl( classLoading, registryPrimer );
37+
return new BasicModelsContextImpl( classLoading, trackImplementors, registryPrimer );
3638
}
3739

3840
private TypePool resolveTypePool(Map<Object, Object> configProperties) {

hibernate-models-bytebuddy/src/main/java/org/hibernate/models/bytebuddy/internal/ByteBuddyModelsContextImpl.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
import net.bytebuddy.pool.TypePool;
2323

24+
import static org.hibernate.models.internal.ModelsClassLogging.MODELS_CLASS_LOGGER;
25+
2426
/**
2527
* Implementation of ByteBuddyModelsContext
2628
*
@@ -39,13 +41,16 @@ public class ByteBuddyModelsContextImpl
3941

4042
public ByteBuddyModelsContextImpl(
4143
TypePool typePool,
44+
boolean trackImplementors,
4245
ClassLoading classLoading,
4346
RegistryPrimer registryPrimer) {
4447
super( classLoading );
4548

49+
MODELS_CLASS_LOGGER.debugf( "Using Byte Buddy support" );
50+
4651
this.typePool = typePool;
4752

48-
this.classDetailsRegistry = new ClassDetailsRegistryImpl( this );
53+
this.classDetailsRegistry = new ClassDetailsRegistryImpl( this, trackImplementors );
4954
this.descriptorRegistry = new AnnotationDescriptorRegistryStandard( this );
5055

5156
primeRegistries( registryPrimer );
@@ -68,7 +73,11 @@ public MutableAnnotationDescriptorRegistry getAnnotationDescriptorRegistry() {
6873

6974
@Override
7075
public StorableContext toStorableForm() {
71-
return new StorableContextImpl( classDetailsRegistry.classDetailsMap(), descriptorRegistry.descriptorMap() );
76+
return new StorableContextImpl(
77+
classDetailsRegistry.isTrackingImplementors(),
78+
classDetailsRegistry.classDetailsMap(),
79+
descriptorRegistry.descriptorMap()
80+
);
7281
}
7382

7483
@Override

hibernate-models-bytebuddy/src/main/java/org/hibernate/models/bytebuddy/internal/ClassDetailsRegistryImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
public class ClassDetailsRegistryImpl extends AbstractClassDetailsRegistry {
1919
private final ClassDetailsBuilderImpl classDetailsBuilder;
2020

21-
public ClassDetailsRegistryImpl(ByteBuddyModelsContextImpl context) {
22-
super( context );
21+
public ClassDetailsRegistryImpl(ByteBuddyModelsContextImpl context, boolean trackImplementors) {
22+
super( trackImplementors, context );
2323
this.classDetailsBuilder = new ClassDetailsBuilderImpl( context );
2424
}
2525

hibernate-models-bytebuddy/src/test/java/org/hibernate/models/testing/shared/intg/ByteBuddyModelsContextFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public ByteBuddyModelsContext createModelContext(
2929
RegistryPrimer registryPrimer,
3030
Class<?>... modelClasses) {
3131
final TypePool byteBuddyTypePool = buildTypePool( modelClasses );
32-
return new ByteBuddyModelsContextImpl( byteBuddyTypePool, SIMPLE_CLASS_LOADING, registryPrimer );
32+
return new ByteBuddyModelsContextImpl( byteBuddyTypePool, true, SIMPLE_CLASS_LOADING, registryPrimer );
3333
}
3434

3535
public static TypePool buildTypePool(Class<?>... modelClasses) {

hibernate-models-jandex/src/main/java/org/hibernate/models/jandex/internal/JandexClassDetailsRegistry.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public class JandexClassDetailsRegistry extends AbstractClassDetailsRegistry {
2323
private final IndexView jandexIndex;
2424
private final ClassDetailsBuilder classDetailsBuilder;
2525

26-
public JandexClassDetailsRegistry(IndexView jandexIndex, ModelsContext context) {
27-
super( context );
26+
public JandexClassDetailsRegistry(IndexView jandexIndex, boolean trackImplementors, ModelsContext context) {
27+
super( trackImplementors, context );
2828
this.jandexIndex = jandexIndex;
2929
this.classDetailsBuilder = new JandexClassDetailsBuilderImpl( jandexIndex, context );
3030
}

hibernate-models-jandex/src/main/java/org/hibernate/models/jandex/internal/JandexModelsContextImpl.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,18 @@ public class JandexModelsContextImpl extends AbstractModelsContext implements Ja
4040

4141
public JandexModelsContextImpl(
4242
IndexView jandexIndex,
43+
boolean trackImplementors,
4344
ClassLoading classLoading,
4445
RegistryPrimer registryPrimer) {
4546
super( classLoading );
4647

48+
MODELS_CLASS_LOGGER.debugf( "Using Jandex support" );
49+
4750
assert jandexIndex != null;
4851
this.jandexIndex = jandexIndex;
4952

50-
MODELS_CLASS_LOGGER.debugf( "Using Jandex support" );
51-
5253
this.descriptorRegistry = new JandexAnnotationDescriptorRegistry( this );
53-
this.classDetailsRegistry = new JandexClassDetailsRegistry( jandexIndex, this );
54+
this.classDetailsRegistry = new JandexClassDetailsRegistry( jandexIndex, trackImplementors,this );
5455

5556
primeRegistries( registryPrimer );
5657
}
@@ -104,6 +105,10 @@ public <V> JandexValueExtractor<V> getJandexValueExtractor(ValueTypeDescriptor<V
104105

105106
@Override
106107
public StorableContext toStorableForm() {
107-
return new StorableContextImpl( classDetailsRegistry.classDetailsMap(), descriptorRegistry.descriptorMap() );
108+
return new StorableContextImpl(
109+
classDetailsRegistry.isTrackingImplementors(),
110+
classDetailsRegistry.classDetailsMap(),
111+
descriptorRegistry.descriptorMap()
112+
);
108113
}
109114
}

hibernate-models-jandex/src/main/java/org/hibernate/models/jandex/internal/JandexModelsContextProvider.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.hibernate.models.internal.BasicModelsContextImpl;
1010
import org.hibernate.models.jandex.Settings;
1111
import org.hibernate.models.spi.ClassLoading;
12+
import org.hibernate.models.spi.ModelsConfiguration;
1213
import org.hibernate.models.spi.ModelsContext;
1314
import org.hibernate.models.spi.RegistryPrimer;
1415
import org.hibernate.models.spi.ModelsContextProvider;
@@ -29,12 +30,13 @@ public ModelsContext produceContext(
2930
RegistryPrimer registryPrimer,
3031
Map<Object, Object> configProperties) {
3132
final IndexView jandexIndex = resolveJandexIndex( configProperties );
33+
final boolean trackImplementors = ModelsConfiguration.shouldTrackImplementors( configProperties );
3234

3335
if ( jandexIndex != null ) {
34-
return new JandexModelsContextImpl( jandexIndex, classLoading, registryPrimer );
36+
return new JandexModelsContextImpl( jandexIndex, trackImplementors, classLoading, registryPrimer );
3537
}
3638

37-
return new BasicModelsContextImpl( classLoading, registryPrimer );
39+
return new BasicModelsContextImpl( classLoading, trackImplementors, registryPrimer );
3840

3941
}
4042

hibernate-models-jandex/src/test/java/org/hibernate/models/testing/shared/intg/JandexModelsContextFactoryImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public JandexModelsContextImpl createModelContext(
2929
RegistryPrimer registryPrimer,
3030
Class<?>... modelClasses) {
3131
final Index jandexIndex = buildJandexIndex( SIMPLE_CLASS_LOADING, modelClasses );
32-
return new JandexModelsContextImpl( jandexIndex, SIMPLE_CLASS_LOADING, registryPrimer );
32+
return new JandexModelsContextImpl( jandexIndex, true, SIMPLE_CLASS_LOADING, registryPrimer );
3333
}
3434

3535
public static Index buildJandexIndex(ClassLoading classLoadingAccess, Class<?>... modelClasses) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright: Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.models;
6+
7+
import org.hibernate.models.spi.ClassDetailsRegistry;
8+
9+
/**
10+
* @author Steve Ebersole
11+
*/
12+
public interface Settings {
13+
/**
14+
* Controls whether to track {@linkplain ClassDetailsRegistry#getDirectImplementors implementors}.
15+
* This tracking has the potential to grow quite large, so this setting allows to
16+
* enable/disable it. By default, this is {@code false}.
17+
*/
18+
@Incubating
19+
String TRACK_IMPLEMENTORS = "hibernate.models.trackImplementors";
20+
}

hibernate-models/src/main/java/org/hibernate/models/internal/AbstractClassDetailsRegistry.java

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,28 @@
3131
*/
3232
public abstract class AbstractClassDetailsRegistry implements MutableClassDetailsRegistry {
3333
protected final ModelsContext context;
34+
private final boolean trackImplementors;
3435

3536
protected final Map<String, ClassDetails> classDetailsMap;
3637

37-
// subtype per type
38-
protected final Map<String, Set<ClassDetails>> directSubTypeMap;
39-
// implementor by interface
38+
// class -> subclasses
39+
protected final Map<String, Set<ClassDetails>> directSubtypeMap;
40+
// interface -> implementations (and specializations)
4041
protected final Map<String, Set<ClassDetails>> directImplementorMap;
4142

42-
protected AbstractClassDetailsRegistry(ModelsContext context) {
43-
this( new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), context );
43+
protected AbstractClassDetailsRegistry(boolean trackImplementors, ModelsContext context) {
44+
this( trackImplementors, new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), context );
4445
}
4546

4647
protected AbstractClassDetailsRegistry(
48+
boolean trackImplementors,
4749
Map<String, ClassDetails> classDetailsMap,
48-
Map<String, Set<ClassDetails>> directSubTypeMap,
50+
Map<String, Set<ClassDetails>> directSubtypeMap,
4951
Map<String, Set<ClassDetails>> directImplementorMap,
5052
ModelsContext context) {
53+
this.trackImplementors = trackImplementors;
5154
this.classDetailsMap = classDetailsMap;
52-
this.directSubTypeMap = directSubTypeMap;
55+
this.directSubtypeMap = directSubtypeMap;
5356
this.directImplementorMap = directImplementorMap;
5457
this.context = context;
5558

@@ -59,6 +62,11 @@ protected AbstractClassDetailsRegistry(
5962
classDetailsMap.put( VOID_OBJECT_CLASS_DETAILS.getClassName(), VOID_OBJECT_CLASS_DETAILS );
6063
}
6164

65+
@Override
66+
public boolean isTrackingImplementors() {
67+
return trackImplementors;
68+
}
69+
6270
@Override
6371
public List<ClassDetails> getDirectSubTypes(String typeName) {
6472
final Set<ClassDetails> directSubtypes = getDirectSubtypes( typeName );
@@ -69,7 +77,7 @@ public List<ClassDetails> getDirectSubTypes(String typeName) {
6977

7078
@Override
7179
public Set<ClassDetails> getDirectSubtypes(String typeName) {
72-
final Set<ClassDetails> directSubtypes = directSubTypeMap.get( typeName );
80+
final Set<ClassDetails> directSubtypes = directSubtypeMap.get( typeName );
7381
return directSubtypes != null ? directSubtypes : Set.of();
7482
}
7583

@@ -86,28 +94,33 @@ public void forEachDirectSubtype(String typeName, ClassDetailsConsumer consumer)
8694

8795
@Override
8896
public Set<ClassDetails> getDirectImplementors(String interfaceName) {
97+
if ( !trackImplementors ) {
98+
return Collections.emptySet();
99+
}
100+
89101
final Set<ClassDetails> implementors = directImplementorMap.get( interfaceName );
90102
return implementors != null ? implementors : Set.of();
91103
}
92104

93105
@Override
94106
public void forEachDirectImplementor(String interfaceName, ClassDetailsConsumer consumer) {
107+
if ( !trackImplementors ) {
108+
return;
109+
}
110+
95111
final Set<ClassDetails> directImplementors = getDirectImplementors( interfaceName );
96112
if ( directImplementors != null ) {
97113
directImplementors.forEach( consumer::consume );
98114
}
99115
}
100116

101117
@Override
102-
public Set<ClassDetails> findConcreteTypes(String base, boolean includeBase) {
103-
final Set<ClassDetails> result = new LinkedHashSet<>();
118+
public void walkConcreteTypes(String base, boolean includeBase, ClassDetailsConsumer consumer) {
104119
walkImplementors( base, includeBase, classDetails -> {
105120
if ( !classDetails.isAbstract() && !classDetails.isInterface() ) {
106-
result.add( classDetails );
121+
consumer.consume( classDetails );
107122
}
108-
109123
});
110-
return result;
111124
}
112125

113126
@Override
@@ -133,10 +146,12 @@ public void walkImplementors(String base, boolean includeBase, ClassDetailsConsu
133146
walkSubtypes( subType, consumer );
134147
} );
135148

136-
forEachDirectImplementor( base, (implementor) -> {
137-
consumer.consume( implementor );
138-
walkInterfaceImplementors( implementor, consumer );
139-
} );
149+
if ( trackImplementors ) {
150+
forEachDirectImplementor( base, (implementor) -> {
151+
consumer.consume( implementor );
152+
walkInterfaceImplementors( implementor, consumer );
153+
} );
154+
}
140155
}
141156

142157
private void walkSubtypes(ClassDetails base, ClassDetailsConsumer consumer) {
@@ -216,24 +231,26 @@ public void addClassDetails(String name, ClassDetails classDetails) {
216231
classDetailsMap.put( name, classDetails );
217232

218233
if ( classDetails.getSuperClass() != null ) {
219-
Set<ClassDetails> subTypes = directSubTypeMap.get( classDetails.getSuperClass().getName() );
234+
Set<ClassDetails> subTypes = directSubtypeMap.get( classDetails.getSuperClass().getName() );
220235
//noinspection Java8MapApi
221236
if ( subTypes == null ) {
222237
subTypes = new LinkedHashSet<>();
223-
directSubTypeMap.put( classDetails.getSuperClass().getName(), subTypes );
238+
directSubtypeMap.put( classDetails.getSuperClass().getName(), subTypes );
224239
}
225240
subTypes.add( classDetails );
226241
}
227242

228-
final List<TypeDetails> implementedInterfaces = classDetails.getImplementedInterfaces();
229-
if ( implementedInterfaces != null ) {
230-
implementedInterfaces.forEach( (implementedInterface) -> {
231-
final Set<ClassDetails> directImplementors = directImplementorMap.computeIfAbsent(
232-
implementedInterface.getName(),
233-
(interfaceName) -> new LinkedHashSet<>()
234-
);
235-
directImplementors.add( classDetails );
236-
} );
243+
if ( trackImplementors ) {
244+
final List<TypeDetails> implementedInterfaces = classDetails.getImplementedInterfaces();
245+
if ( implementedInterfaces != null ) {
246+
implementedInterfaces.forEach( (implementedInterface) -> {
247+
final Set<ClassDetails> directImplementors = directImplementorMap.computeIfAbsent(
248+
implementedInterface.getName(),
249+
(interfaceName) -> new LinkedHashSet<>()
250+
);
251+
directImplementors.add( classDetails );
252+
} );
253+
}
237254
}
238255
}
239256

@@ -281,7 +298,7 @@ public Map<String, ClassDetails> getClassDetailsMap() {
281298
}
282299

283300
public Map<String, Set<ClassDetails>> getDirectSubTypeMap() {
284-
return Collections.unmodifiableMap( directSubTypeMap );
301+
return Collections.unmodifiableMap( directSubtypeMap );
285302
}
286303

287304
public Map<String, Set<ClassDetails>> getDirectImplementorMap() {

0 commit comments

Comments
 (0)