use of net.bytebuddy.implementation.Implementation in project hibernate-orm by hibernate.
the class EnhancerImpl method doEnhance.
private DynamicType.Builder<?> doEnhance(DynamicType.Builder<?> builder, TypeDescription managedCtClass) {
// can't effectively enhance interfaces
if (managedCtClass.isInterface()) {
log.debugf("Skipping enhancement of [%s]: it's an interface!", managedCtClass.getName());
return null;
}
// skip already enhanced classes
if (alreadyEnhanced(managedCtClass)) {
log.debugf("Skipping enhancement of [%s]: already enhanced", managedCtClass.getName());
return null;
}
PersistentAttributeTransformer transformer = PersistentAttributeTransformer.collectPersistentFields(managedCtClass, enhancementContext, classPool);
if (enhancementContext.isEntityClass(managedCtClass)) {
log.infof("Enhancing [%s] as Entity", managedCtClass.getName());
builder = builder.implement(ManagedEntity.class).defineMethod(EnhancerConstants.ENTITY_INSTANCE_GETTER_NAME, Object.class, Visibility.PUBLIC).intercept(FixedValue.self());
builder = addFieldWithGetterAndSetter(builder, EntityEntry.class, EnhancerConstants.ENTITY_ENTRY_FIELD_NAME, EnhancerConstants.ENTITY_ENTRY_GETTER_NAME, EnhancerConstants.ENTITY_ENTRY_SETTER_NAME);
builder = addFieldWithGetterAndSetter(builder, ManagedEntity.class, EnhancerConstants.PREVIOUS_FIELD_NAME, EnhancerConstants.PREVIOUS_GETTER_NAME, EnhancerConstants.PREVIOUS_SETTER_NAME);
builder = addFieldWithGetterAndSetter(builder, ManagedEntity.class, EnhancerConstants.NEXT_FIELD_NAME, EnhancerConstants.NEXT_GETTER_NAME, EnhancerConstants.NEXT_SETTER_NAME);
builder = addInterceptorHandling(builder, managedCtClass);
if (enhancementContext.doDirtyCheckingInline(managedCtClass)) {
if (collectCollectionFields(managedCtClass).isEmpty()) {
builder = builder.implement(SelfDirtinessTracker.class).defineField(EnhancerConstants.TRACKER_FIELD_NAME, DirtyTracker.class, FieldPersistence.TRANSIENT, Visibility.PRIVATE).annotateField(AnnotationDescription.Builder.ofType(Transient.class).build()).defineMethod(EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC).withParameters(String.class).intercept(Advice.to(CodeTemplates.TrackChange.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC).intercept(Advice.to(CodeTemplates.GetDirtyAttributesWithoutCollections.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC).intercept(Advice.to(CodeTemplates.AreFieldsDirtyWithoutCollections.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC).intercept(Advice.to(CodeTemplates.ClearDirtyAttributesWithoutCollections.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC).withParameters(boolean.class).intercept(Advice.to(CodeTemplates.SuspendDirtyTracking.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC).intercept(Advice.to(CodeTemplates.GetCollectionTrackerWithoutCollections.class).wrap(StubMethod.INSTANCE));
} else {
builder = builder.implement(ExtendedSelfDirtinessTracker.class).defineField(EnhancerConstants.TRACKER_FIELD_NAME, DirtyTracker.class, FieldPersistence.TRANSIENT, Visibility.PRIVATE).annotateField(AnnotationDescription.Builder.ofType(Transient.class).build()).defineField(EnhancerConstants.TRACKER_COLLECTION_NAME, CollectionTracker.class, FieldPersistence.TRANSIENT, Visibility.PRIVATE).annotateField(AnnotationDescription.Builder.ofType(Transient.class).build()).defineMethod(EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC).withParameters(String.class).intercept(Advice.to(CodeTemplates.TrackChange.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC).intercept(Advice.to(CodeTemplates.GetDirtyAttributes.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC).intercept(Advice.to(CodeTemplates.AreFieldsDirty.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC).intercept(Advice.to(CodeTemplates.ClearDirtyAttributes.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC).withParameters(boolean.class).intercept(Advice.to(CodeTemplates.SuspendDirtyTracking.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC).intercept(FieldAccessor.ofField(EnhancerConstants.TRACKER_COLLECTION_NAME));
Implementation isDirty = StubMethod.INSTANCE, getDirtyNames = StubMethod.INSTANCE, clearDirtyNames = StubMethod.INSTANCE;
for (FieldDescription collectionField : collectCollectionFields(managedCtClass)) {
if (collectionField.getType().asErasure().isAssignableTo(Map.class)) {
isDirty = Advice.withCustomMapping().bind(CodeTemplates.FieldName.class, collectionField.getName()).bind(CodeTemplates.FieldValue.class, collectionField).to(CodeTemplates.MapAreCollectionFieldsDirty.class).wrap(isDirty);
getDirtyNames = Advice.withCustomMapping().bind(CodeTemplates.FieldName.class, collectionField.getName()).bind(CodeTemplates.FieldValue.class, collectionField).to(CodeTemplates.MapGetCollectionFieldDirtyNames.class).wrap(getDirtyNames);
clearDirtyNames = Advice.withCustomMapping().bind(CodeTemplates.FieldName.class, collectionField.getName()).bind(CodeTemplates.FieldValue.class, collectionField).to(CodeTemplates.MapGetCollectionClearDirtyNames.class).wrap(clearDirtyNames);
} else {
isDirty = Advice.withCustomMapping().bind(CodeTemplates.FieldName.class, collectionField.getName()).bind(CodeTemplates.FieldValue.class, collectionField).to(CodeTemplates.CollectionAreCollectionFieldsDirty.class).wrap(isDirty);
getDirtyNames = Advice.withCustomMapping().bind(CodeTemplates.FieldName.class, collectionField.getName()).bind(CodeTemplates.FieldValue.class, collectionField).to(CodeTemplates.CollectionGetCollectionFieldDirtyNames.class).wrap(getDirtyNames);
clearDirtyNames = Advice.withCustomMapping().bind(CodeTemplates.FieldName.class, collectionField.getName()).bind(CodeTemplates.FieldValue.class, collectionField).to(CodeTemplates.CollectionGetCollectionClearDirtyNames.class).wrap(clearDirtyNames);
}
}
if (enhancementContext.hasLazyLoadableAttributes(managedCtClass)) {
clearDirtyNames = Advice.to(CodeTemplates.InitializeLazyAttributeLoadingInterceptor.class).wrap(clearDirtyNames);
}
builder = builder.defineMethod(EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME, boolean.class, Visibility.PUBLIC).intercept(isDirty).defineMethod(EnhancerConstants.TRACKER_COLLECTION_CHANGED_FIELD_NAME, void.class, Visibility.PUBLIC).withParameters(DirtyTracker.class).intercept(getDirtyNames).defineMethod(EnhancerConstants.TRACKER_COLLECTION_CLEAR_NAME, void.class, Visibility.PUBLIC).intercept(Advice.withCustomMapping().to(CodeTemplates.ClearDirtyCollectionNames.class).wrap(StubMethod.INSTANCE)).defineMethod(ExtendedSelfDirtinessTracker.REMOVE_DIRTY_FIELDS_NAME, void.class, Visibility.PUBLIC).withParameters(LazyAttributeLoadingInterceptor.class).intercept(clearDirtyNames);
}
}
return transformer.applyTo(builder, false);
} else if (enhancementContext.isCompositeClass(managedCtClass)) {
log.infof("Enhancing [%s] as Composite", managedCtClass.getName());
builder = builder.implement(ManagedComposite.class);
builder = addInterceptorHandling(builder, managedCtClass);
if (enhancementContext.doDirtyCheckingInline(managedCtClass)) {
builder = builder.implement(CompositeTracker.class).defineField(EnhancerConstants.TRACKER_COMPOSITE_FIELD_NAME, CompositeOwnerTracker.class, FieldPersistence.TRANSIENT, Visibility.PRIVATE).annotateField(AnnotationDescription.Builder.ofType(Transient.class).build()).defineMethod(EnhancerConstants.TRACKER_COMPOSITE_SET_OWNER, void.class, Visibility.PUBLIC).withParameters(String.class, CompositeOwner.class).intercept(Advice.to(CodeTemplates.SetOwner.class).wrap(StubMethod.INSTANCE)).defineMethod(EnhancerConstants.TRACKER_COMPOSITE_CLEAR_OWNER, void.class, Visibility.PUBLIC).withParameters(String.class).intercept(Advice.to(CodeTemplates.ClearOwner.class).wrap(StubMethod.INSTANCE));
}
return transformer.applyTo(builder, false);
} else if (enhancementContext.isMappedSuperclassClass(managedCtClass)) {
log.infof("Enhancing [%s] as MappedSuperclass", managedCtClass.getName());
builder = builder.implement(ManagedMappedSuperclass.class);
return transformer.applyTo(builder, true);
} else if (enhancementContext.doExtendedEnhancement(managedCtClass)) {
log.infof("Extended enhancement of [%s]", managedCtClass.getName());
return transformer.applyExtended(builder);
} else {
log.debugf("Skipping enhancement of [%s]: not entity or composite", managedCtClass.getName());
return null;
}
}
use of net.bytebuddy.implementation.Implementation in project beam by apache.
the class ByteBuddyUtils method createCollectionTransformFunction.
// When processing a container (e.g. List<T>) we need to recursively process the element type.
// This function
// generates a subclass of Function that can be used to recursively transform each element of the
// container.
static Class createCollectionTransformFunction(Type fromType, Type toType, Function<StackManipulation, StackManipulation> convertElement) {
// Generate a TypeDescription for the class we want to generate.
TypeDescription.Generic functionGenericType = TypeDescription.Generic.Builder.parameterizedType(Function.class, Primitives.wrap((Class) fromType), Primitives.wrap((Class) toType)).build();
DynamicType.Builder<Function> builder = (DynamicType.Builder<Function>) BYTE_BUDDY.with(new InjectPackageStrategy((Class) fromType)).subclass(functionGenericType).method(ElementMatchers.named("apply")).intercept(new Implementation() {
@Override
public ByteCodeAppender appender(Target target) {
return (methodVisitor, implementationContext, instrumentedMethod) -> {
// this + method parameters.
int numLocals = 1 + instrumentedMethod.getParameters().size();
StackManipulation readValue = MethodVariableAccess.REFERENCE.loadFrom(1);
StackManipulation stackManipulation = new StackManipulation.Compound(convertElement.apply(readValue), MethodReturn.REFERENCE);
StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
return new ByteCodeAppender.Size(size.getMaximalSize(), numLocals);
};
}
@Override
public InstrumentedType prepare(InstrumentedType instrumentedType) {
return instrumentedType;
}
});
return builder.visit(new AsmVisitorWrapper.ForDeclaredMethods().writerFlags(ClassWriter.COMPUTE_FRAMES)).make().load(ReflectHelpers.findClassLoader(((Class) fromType).getClassLoader()), ClassLoadingStrategy.Default.INJECTION).getLoaded();
}
use of net.bytebuddy.implementation.Implementation in project hibernate-orm by hibernate.
the class PersistentAttributeTransformer method fieldWriter.
private Implementation fieldWriter(FieldDescription enhancedField) {
Implementation implementation;
if (!enhancementContext.hasLazyLoadableAttributes(managedCtClass) || !enhancementContext.isLazyLoadable(enhancedField)) {
if (enhancedField.getDeclaringType().asErasure().equals(managedCtClass)) {
implementation = FieldAccessor.ofField(enhancedField.getName()).in(enhancedField.getDeclaringType().asErasure());
} else {
implementation = new Implementation.Simple(new FieldMethodWriter(managedCtClass, enhancedField));
}
} else {
implementation = new Implementation.Simple(FieldWriterAppender.of(managedCtClass, enhancedField));
}
implementation = InlineDirtyCheckingHandler.wrap(managedCtClass, enhancementContext, enhancedField, implementation);
return BiDirectionalAssociationHandler.wrap(managedCtClass, enhancementContext, enhancedField, implementation);
}
Aggregations