6
6
*/
7
7
package org .hibernate .bytecode .enhance .internal .bytebuddy ;
8
8
9
- import java .io .IOException ;
10
9
import java .lang .annotation .Annotation ;
11
10
import java .lang .reflect .Modifier ;
12
11
import java .util .ArrayList ;
13
12
import java .util .Collection ;
14
13
import java .util .Collections ;
15
14
import java .util .List ;
16
15
import java .util .Map ;
16
+ import java .util .Objects ;
17
17
import java .util .Optional ;
18
- import java .util .concurrent .ConcurrentHashMap ;
19
18
import java .util .function .Supplier ;
20
19
21
20
import org .hibernate .Version ;
66
65
import net .bytebuddy .implementation .FixedValue ;
67
66
import net .bytebuddy .implementation .Implementation ;
68
67
import net .bytebuddy .implementation .StubMethod ;
69
- import net .bytebuddy .pool .TypePool ;
70
68
71
69
import static net .bytebuddy .matcher .ElementMatchers .isDefaultFinalizer ;
72
70
@@ -93,9 +91,7 @@ public Class<? extends Annotation> annotationType() {
93
91
94
92
protected final ByteBuddyEnhancementContext enhancementContext ;
95
93
private final ByteBuddyState byteBuddyState ;
96
-
97
- private final EnhancerClassFileLocator classFileLocator ;
98
- private final TypePool typePool ;
94
+ private final EnhancerClassLocator typePool ;
99
95
100
96
/**
101
97
* Extract the following constants so that enhancement on large projects
@@ -126,10 +122,20 @@ public Class<? extends Annotation> annotationType() {
126
122
* @param byteBuddyState refers to the ByteBuddy instance to use
127
123
*/
128
124
public EnhancerImpl (final EnhancementContext enhancementContext , final ByteBuddyState byteBuddyState ) {
125
+ this ( enhancementContext , byteBuddyState , ModelTypePool .buildModelTypePool ( enhancementContext .getLoadingClassLoader () ) );
126
+ }
127
+
128
+ /**
129
+ * Expert level constructor, this allows for more control of state and bytecode loading,
130
+ * which allows integrators to optimise for particular contexts of use.
131
+ * @param enhancementContext
132
+ * @param byteBuddyState
133
+ * @param classLocator
134
+ */
135
+ public EnhancerImpl (final EnhancementContext enhancementContext , final ByteBuddyState byteBuddyState , final EnhancerClassLocator classLocator ) {
129
136
this .enhancementContext = new ByteBuddyEnhancementContext ( enhancementContext );
130
- this .byteBuddyState = byteBuddyState ;
131
- this .classFileLocator = new EnhancerClassFileLocator ( enhancementContext .getLoadingClassLoader () );
132
- this .typePool = buildTypePool ( classFileLocator );
137
+ this .byteBuddyState = Objects .requireNonNull ( byteBuddyState );
138
+ this .typePool = Objects .requireNonNull ( classLocator );
133
139
}
134
140
135
141
/**
@@ -147,13 +153,13 @@ public EnhancerImpl(final EnhancementContext enhancementContext, final ByteBuddy
147
153
public byte [] enhance (String className , byte [] originalBytes ) throws EnhancementException {
148
154
//Classpool#describe does not accept '/' in the description name as it expects a class name. See HHH-12545
149
155
final String safeClassName = className .replace ( '/' , '.' );
150
- classFileLocator .registerClassNameAndBytes ( safeClassName , originalBytes );
156
+ typePool .registerClassNameAndBytes ( safeClassName , originalBytes );
151
157
try {
152
158
final TypeDescription typeDescription = typePool .describe ( safeClassName ).resolve ();
153
159
154
160
return byteBuddyState .rewrite ( typePool , safeClassName , byteBuddy -> doEnhance (
155
161
() -> byteBuddy .ignore ( isDefaultFinalizer () )
156
- .redefine ( typeDescription , ClassFileLocator . Simple . of ( safeClassName , originalBytes ) )
162
+ .redefine ( typeDescription , typePool . asClassFileLocator ( ) )
157
163
.annotateType ( HIBERNATE_VERSION_ANNOTATION ),
158
164
typeDescription
159
165
) );
@@ -165,14 +171,14 @@ public byte[] enhance(String className, byte[] originalBytes) throws Enhancement
165
171
throw new EnhancementException ( "Failed to enhance class " + className , e );
166
172
}
167
173
finally {
168
- classFileLocator .deregisterClassNameAndBytes ( safeClassName );
174
+ typePool .deregisterClassNameAndBytes ( safeClassName );
169
175
}
170
176
}
171
177
172
178
@ Override
173
179
public void discoverTypes (String className , byte [] originalBytes ) {
174
180
if ( originalBytes != null ) {
175
- classFileLocator .registerClassNameAndBytes ( className , originalBytes );
181
+ typePool .registerClassNameAndBytes ( className , originalBytes );
176
182
}
177
183
try {
178
184
final TypeDescription typeDescription = typePool .describe ( className ).resolve ();
@@ -183,14 +189,10 @@ public void discoverTypes(String className, byte[] originalBytes) {
183
189
throw new EnhancementException ( "Failed to discover types for class " + className , e );
184
190
}
185
191
finally {
186
- classFileLocator .deregisterClassNameAndBytes ( className );
192
+ typePool .deregisterClassNameAndBytes ( className );
187
193
}
188
194
}
189
195
190
- private TypePool buildTypePool (final ClassFileLocator classFileLocator ) {
191
- return TypePool .Default .WithLazyResolution .of ( classFileLocator );
192
- }
193
-
194
196
private DynamicType .Builder <?> doEnhance (Supplier <DynamicType .Builder <?>> builderSupplier , TypeDescription managedCtClass ) {
195
197
// can't effectively enhance interfaces
196
198
if ( managedCtClass .isInterface () ) {
@@ -652,39 +654,4 @@ else if ( access != null && access.load().value() == AccessType.FIELD ) {
652
654
}
653
655
}
654
656
655
- private static class EnhancerClassFileLocator extends ClassFileLocator .ForClassLoader {
656
- private final ConcurrentHashMap <String , Resolution > resolutions = new ConcurrentHashMap <>();
657
-
658
- /**
659
- * Creates a new class file locator for the given class loader.
660
- *
661
- * @param classLoader The class loader to query which must not be the bootstrap class loader, i.e. {@code null}.
662
- */
663
- protected EnhancerClassFileLocator (ClassLoader classLoader ) {
664
- super ( classLoader );
665
- }
666
-
667
- @ Override
668
- public Resolution locate (String className ) throws IOException {
669
- assert className != null ;
670
- final Resolution resolution = resolutions .get ( className );
671
- if ( resolution != null ) {
672
- return resolution ;
673
- }
674
- else {
675
- return super .locate ( className );
676
- }
677
- }
678
-
679
- void registerClassNameAndBytes (String className , byte [] bytes ) {
680
- assert className != null ;
681
- assert bytes != null ;
682
- resolutions .put ( className , new Resolution .Explicit ( bytes ) );
683
- }
684
-
685
- void deregisterClassNameAndBytes (String className ) {
686
- resolutions .remove ( className );
687
- }
688
- }
689
-
690
657
}
0 commit comments