Skip to content

Commit 31f1b28

Browse files
committed
#107 - hibernate-models-bytebuddy
1 parent 9d59cbc commit 31f1b28

File tree

67 files changed

+3226
-28
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+3226
-28
lines changed

buildSrc/src/main/groovy/shared-testing.gradle

+4-7
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ plugins {
1111
// Wire in the shared-tests
1212
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1313

14-
// link the
1514
configurations {
1615
sharedTestClasses {
1716
canBeConsumed = false
@@ -24,22 +23,20 @@ configurations {
2423
sharedTestRuntimeClasspath {
2524
canBeConsumed = false
2625
canBeResolved = true
27-
extendsFrom testRuntimeClasspath
2826
}
2927
}
3028

3129
dependencies {
3230
testImplementation project( ":hibernate-models-testing" )
3331

34-
sharedTestClasses project(path: ':hibernate-models', configuration: 'exposedTestClasses')
35-
sharedTestResources project(path: ':hibernate-models', configuration: 'exposedTestResources')
36-
sharedTestRuntimeClasspath project(path: ':hibernate-models', configuration: 'exposedTestRuntimeClasspath')
32+
sharedTestClasses project(path: ':hibernate-models', configuration: 'exportedTestClasses')
33+
sharedTestResources project(path: ':hibernate-models', configuration: 'exportedTestResources')
34+
35+
sharedTestRuntimeClasspath project(path: ':hibernate-models', configuration: 'exportedTestRuntimeClasspath')
3736
}
3837

3938
tasks.named( "test", Test ) {
40-
// use the configurations defined above, which depends on the configurations in `:architecture-tests`
4139
testClassesDirs += configurations.sharedTestClasses
42-
4340
classpath += configurations.sharedTestResources
4441
classpath += configurations.sharedTestRuntimeClasspath
4542
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
plugins {
2+
id "published-java-module"
3+
id "shared-testing"
4+
}
5+
6+
description = "Support for hibernate-models based on ByteBuddy (isolated dependency)"
7+
8+
repositories {
9+
mavenCentral()
10+
}
11+
12+
dependencies {
13+
api project( ":hibernate-models" )
14+
15+
implementation libs.byteBuddy
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright: Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.models.bytebuddy;
6+
7+
/**
8+
* Settings for hibernate-models ByteBuddy support
9+
*
10+
* @author Steve Ebersole
11+
*/
12+
public interface Settings {
13+
/**
14+
* Used to pass the ByteBuddy {@linkplain net.bytebuddy.pool.TypePool}.
15+
*/
16+
String TYPE_POOL_PARAM = "hibernate.models.bytebuddy.typePool";
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright: Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.models.bytebuddy.internal;
6+
7+
import java.lang.annotation.Annotation;
8+
import java.util.Map;
9+
10+
import org.hibernate.models.bytebuddy.spi.ByteBuddyModelsContext;
11+
import org.hibernate.models.internal.AnnotationTargetSupport;
12+
13+
import net.bytebuddy.description.annotation.AnnotationSource;
14+
15+
/**
16+
* @author Steve Ebersole
17+
*/
18+
public abstract class AbstractAnnotationTarget implements AnnotationTargetSupport {
19+
private final ByteBuddyModelsContext modelContext;
20+
21+
private Map<Class<? extends Annotation>, ? extends Annotation> usageMap;
22+
23+
public AbstractAnnotationTarget(ByteBuddyModelsContext modelContext) {
24+
this.modelContext = modelContext;
25+
}
26+
27+
public ByteBuddyModelsContext getModelContext() {
28+
return modelContext;
29+
}
30+
31+
protected abstract AnnotationSource getAnnotationSource();
32+
33+
@Override
34+
public Map<Class<? extends Annotation>, ? extends Annotation> getUsageMap() {
35+
if ( usageMap == null ) {
36+
usageMap = AnnotationUsageBuilder.collectUsages( getAnnotationSource(), modelContext );
37+
}
38+
return usageMap;
39+
}
40+
41+
@Override
42+
public void clearAnnotationUsages() {
43+
getUsageMap().clear();
44+
}
45+
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright: Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.models.bytebuddy.internal;
6+
7+
import java.lang.annotation.Annotation;
8+
9+
import org.hibernate.models.bytebuddy.spi.ByteBuddyModelsContext;
10+
import org.hibernate.models.internal.StandardAnnotationDescriptor;
11+
import org.hibernate.models.spi.AnnotationDescriptor;
12+
import org.hibernate.models.spi.SourceModelBuildingContext;
13+
14+
import net.bytebuddy.description.annotation.AnnotationDescription;
15+
16+
/**
17+
* @author Steve Ebersole
18+
*/
19+
public class AnnotationDescriptorImpl<A extends Annotation> extends StandardAnnotationDescriptor<A> {
20+
public AnnotationDescriptorImpl(
21+
Class<A> annotationType,
22+
SourceModelBuildingContext buildingContext) {
23+
super( annotationType, buildingContext );
24+
}
25+
26+
public AnnotationDescriptorImpl(
27+
Class<A> annotationType,
28+
AnnotationDescriptor<?> repeatableContainer,
29+
SourceModelBuildingContext buildingContext) {
30+
super( annotationType, repeatableContainer, buildingContext );
31+
}
32+
33+
public A createUsage(AnnotationDescription annotationDescription, ByteBuddyModelsContext context) {
34+
return AnnotationUsageBuilder.makeUsage( annotationDescription, this, context );
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright: Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.models.bytebuddy.internal;
6+
7+
import java.lang.annotation.Annotation;
8+
import java.util.Map;
9+
10+
import org.hibernate.models.internal.AnnotationDescriptorRegistryStandard;
11+
import org.hibernate.models.spi.AnnotationDescriptor;
12+
import org.hibernate.models.spi.SourceModelBuildingContext;
13+
14+
/**
15+
* @author Steve Ebersole
16+
*/
17+
public class AnnotationDescriptorRegistryImpl extends AnnotationDescriptorRegistryStandard {
18+
public AnnotationDescriptorRegistryImpl(SourceModelBuildingContext modelBuildingContext) {
19+
super( modelBuildingContext );
20+
}
21+
22+
@Override
23+
protected <A extends Annotation> AnnotationDescriptor<A> buildAnnotationDescriptor(
24+
Class<A> javaType,
25+
AnnotationDescriptor<? extends Annotation> containerDescriptor) {
26+
return new AnnotationDescriptorImpl<>( javaType, containerDescriptor, getModelBuildingContext() );
27+
}
28+
29+
public Map<Class<? extends Annotation>, AnnotationDescriptor<? extends Annotation>> getDescriptorMap() {
30+
return descriptorMap;
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright: Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.models.bytebuddy.internal;
6+
7+
import java.lang.annotation.Annotation;
8+
import java.lang.annotation.Documented;
9+
import java.lang.annotation.Repeatable;
10+
import java.lang.annotation.Retention;
11+
import java.lang.annotation.Target;
12+
import java.util.Collections;
13+
import java.util.HashMap;
14+
import java.util.Map;
15+
import java.util.concurrent.ConcurrentHashMap;
16+
import java.util.function.BiConsumer;
17+
18+
import org.hibernate.models.bytebuddy.spi.ByteBuddyModelsContext;
19+
import org.hibernate.models.bytebuddy.spi.ValueExtractor;
20+
import org.hibernate.models.internal.util.CollectionHelper;
21+
import org.hibernate.models.spi.AnnotationDescriptor;
22+
import org.hibernate.models.spi.AnnotationDescriptorRegistry;
23+
import org.hibernate.models.spi.AttributeDescriptor;
24+
import org.hibernate.models.spi.SourceModelBuildingContext;
25+
26+
import net.bytebuddy.description.annotation.AnnotationDescription;
27+
import net.bytebuddy.description.annotation.AnnotationList;
28+
import net.bytebuddy.description.annotation.AnnotationSource;
29+
30+
/**
31+
* Helper for building annotation usages/instances based on
32+
* Jandex {@linkplain AnnotationDescription} references
33+
*
34+
* @author Steve Ebersole
35+
*/
36+
public class AnnotationUsageBuilder {
37+
public static <A extends Annotation> A makeUsage(
38+
AnnotationDescription annotationDescription,
39+
AnnotationDescriptor<A> annotationDescriptor,
40+
SourceModelBuildingContext modelContext) {
41+
final Map<String, Object> attributeValues = extractAttributeValues(
42+
annotationDescription,
43+
annotationDescriptor,
44+
modelContext
45+
);
46+
return annotationDescriptor.createUsage( attributeValues, modelContext );
47+
}
48+
49+
private static <A extends Annotation> Map<String, Object> extractAttributeValues(
50+
AnnotationDescription annotationDescription,
51+
AnnotationDescriptor<A> annotationDescriptor,
52+
SourceModelBuildingContext modelContext) {
53+
54+
if ( CollectionHelper.isEmpty( annotationDescriptor.getAttributes() ) ) {
55+
return Collections.emptyMap();
56+
}
57+
58+
final ConcurrentHashMap<String, Object> valueMap = new ConcurrentHashMap<>();
59+
for ( int i = 0; i < annotationDescriptor.getAttributes().size(); i++ ) {
60+
final AttributeDescriptor<?> attributeDescriptor = annotationDescriptor.getAttributes().get( i );
61+
final ValueExtractor<?> extractor = modelContext
62+
.as( ByteBuddyModelContextImpl.class )
63+
.getValueExtractor( attributeDescriptor.getTypeDescriptor() );
64+
final Object attributeValue = extractor.extractValue(
65+
annotationDescription,
66+
attributeDescriptor.getName(),
67+
modelContext
68+
);
69+
valueMap.put( attributeDescriptor.getName(), attributeValue );
70+
}
71+
return valueMap;
72+
}
73+
74+
public static Map<Class<? extends Annotation>, ? extends Annotation> collectUsages(
75+
AnnotationSource annotationSource,
76+
ByteBuddyModelsContext modelContext) {
77+
if ( annotationSource == null ) {
78+
return Collections.emptyMap();
79+
}
80+
final Map<Class<? extends Annotation>, Annotation> result = new HashMap<>();
81+
processAnnotations(
82+
annotationSource.getDeclaredAnnotations(),
83+
result::put,
84+
modelContext
85+
);
86+
return result;
87+
}
88+
89+
/**
90+
* Process annotations creating usage instances passed back to the consumer
91+
*/
92+
public static void processAnnotations(
93+
AnnotationList annotations,
94+
BiConsumer<Class<? extends Annotation>, Annotation> consumer,
95+
ByteBuddyModelsContext buildingContext) {
96+
final AnnotationDescriptorRegistry annotationDescriptorRegistry = buildingContext.getAnnotationDescriptorRegistry();
97+
98+
for ( AnnotationDescription annotation : annotations ) {
99+
if ( annotation.getAnnotationType().represents( Documented.class )
100+
|| annotation.getAnnotationType().represents( Repeatable.class )
101+
|| annotation.getAnnotationType().represents( Retention.class )
102+
|| annotation.getAnnotationType().represents( Target.class ) ) {
103+
continue;
104+
}
105+
106+
final Class<? extends Annotation> annotationType = buildingContext
107+
.getClassLoading()
108+
.classForName( annotation.getAnnotationType().getTypeName() );
109+
final AnnotationDescriptor<?> annotationDescriptor = annotationDescriptorRegistry.getDescriptor( annotationType );
110+
final Annotation usage = makeUsage(
111+
annotation,
112+
annotationDescriptor,
113+
buildingContext
114+
);
115+
consumer.accept( annotationType, usage );
116+
}
117+
}
118+
}

0 commit comments

Comments
 (0)