/*
 * Copyright 2014 - 2020 Rafael Winterhalter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.bytebuddy.implementation.attribute;

import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.annotation.AnnotationList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeList;
import org.objectweb.asm.ClassVisitor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

An appender that writes attributes or annotations to a given ASM ClassVisitor.
/** * An appender that writes attributes or annotations to a given ASM {@link org.objectweb.asm.ClassVisitor}. */
public interface TypeAttributeAppender {
Applies this type attribute appender.
Params:
  • classVisitor – The class visitor to which the annotations of this visitor should be written to.
  • instrumentedType – A description of the instrumented type that is target of the ongoing instrumentation.
  • annotationValueFilter – The annotation value filter to apply when writing annotations.
/** * Applies this type attribute appender. * * @param classVisitor The class visitor to which the annotations of this visitor should be written to. * @param instrumentedType A description of the instrumented type that is target of the ongoing instrumentation. * @param annotationValueFilter The annotation value filter to apply when writing annotations. */
void apply(ClassVisitor classVisitor, TypeDescription instrumentedType, AnnotationValueFilter annotationValueFilter);
A type attribute appender that does not append any attributes.
/** * A type attribute appender that does not append any attributes. */
enum NoOp implements TypeAttributeAppender {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public void apply(ClassVisitor classVisitor, TypeDescription instrumentedType, AnnotationValueFilter annotationValueFilter) { /* do nothing */ } }
An attribute appender that writes all annotations that are found on a given target type to the instrumented type this type attribute appender is applied onto. The visibility for the annotation will be inferred from the annotations' RetentionPolicy.
/** * An attribute appender that writes all annotations that are found on a given target type to the * instrumented type this type attribute appender is applied onto. The visibility for the annotation * will be inferred from the annotations' {@link java.lang.annotation.RetentionPolicy}. */
enum ForInstrumentedType implements TypeAttributeAppender {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public void apply(ClassVisitor classVisitor, TypeDescription instrumentedType, AnnotationValueFilter annotationValueFilter) { AnnotationAppender annotationAppender = new AnnotationAppender.Default(new AnnotationAppender.Target.OnType(classVisitor)); annotationAppender = AnnotationAppender.ForTypeAnnotations.ofTypeVariable(annotationAppender, annotationValueFilter, AnnotationAppender.ForTypeAnnotations.VARIABLE_ON_TYPE, instrumentedType.getTypeVariables()); TypeDescription.Generic superClass = instrumentedType.getSuperClass(); if (superClass != null) { annotationAppender = superClass.accept(AnnotationAppender.ForTypeAnnotations.ofSuperClass(annotationAppender, annotationValueFilter)); } int interfaceIndex = 0; for (TypeDescription.Generic interfaceType : instrumentedType.getInterfaces()) { annotationAppender = interfaceType.accept(AnnotationAppender.ForTypeAnnotations.ofInterfaceType(annotationAppender, annotationValueFilter, interfaceIndex++)); } for (AnnotationDescription annotation : instrumentedType.getDeclaredAnnotations()) { annotationAppender = annotationAppender.append(annotation, annotationValueFilter); } }
A type attribute appender that writes all annotations of the instrumented but excludes annotations up to a given index.
/** * A type attribute appender that writes all annotations of the instrumented but excludes annotations up to * a given index. */
@HashCodeAndEqualsPlugin.Enhance public static class Differentiating implements TypeAttributeAppender {
The index of the first annotations that should be directly written onto the type.
/** * The index of the first annotations that should be directly written onto the type. */
private final int annotationIndex;
The index of the first type variable for which type annotations should be directly written onto the type.
/** * The index of the first type variable for which type annotations should be directly written onto the type. */
private final int typeVariableIndex;
The index of the first interface type for which type annotations should be directly written onto the type.
/** * The index of the first interface type for which type annotations should be directly written onto the type. */
private final int interfaceTypeIndex;
Creates a new differentiating type attribute appender.
Params:
  • typeDescription – The type for which to resolve all exclusion indices.
/** * Creates a new differentiating type attribute appender. * * @param typeDescription The type for which to resolve all exclusion indices. */
public Differentiating(TypeDescription typeDescription) { this(typeDescription.getDeclaredAnnotations().size(), typeDescription.getTypeVariables().size(), typeDescription.getInterfaces().size()); }
Creates a new differentiating type attribute appender.
Params:
  • annotationIndex – The index of the first annotations that should be directly written onto the type.
  • typeVariableIndex – The index of the first interface type for which type annotations should be directly written onto the type.
  • interfaceTypeIndex – The index of the first interface type for which type annotations should be directly written onto the type.
/** * Creates a new differentiating type attribute appender. * * @param annotationIndex The index of the first annotations that should be directly written onto the type. * @param typeVariableIndex The index of the first interface type for which type annotations should be directly written onto the type. * @param interfaceTypeIndex The index of the first interface type for which type annotations should be directly written onto the type. */
protected Differentiating(int annotationIndex, int typeVariableIndex, int interfaceTypeIndex) { this.annotationIndex = annotationIndex; this.typeVariableIndex = typeVariableIndex; this.interfaceTypeIndex = interfaceTypeIndex; }
{@inheritDoc}
/** * {@inheritDoc} */
public void apply(ClassVisitor classVisitor, TypeDescription instrumentedType, AnnotationValueFilter annotationValueFilter) { AnnotationAppender annotationAppender = new AnnotationAppender.Default(new AnnotationAppender.Target.OnType(classVisitor)); AnnotationAppender.ForTypeAnnotations.ofTypeVariable(annotationAppender, annotationValueFilter, AnnotationAppender.ForTypeAnnotations.VARIABLE_ON_TYPE, typeVariableIndex, instrumentedType.getTypeVariables()); TypeList.Generic interfaceTypes = instrumentedType.getInterfaces(); int interfaceTypeIndex = this.interfaceTypeIndex; for (TypeDescription.Generic interfaceType : interfaceTypes.subList(this.interfaceTypeIndex, interfaceTypes.size())) { annotationAppender = interfaceType.accept(AnnotationAppender.ForTypeAnnotations.ofInterfaceType(annotationAppender, annotationValueFilter, interfaceTypeIndex++)); } AnnotationList declaredAnnotations = instrumentedType.getDeclaredAnnotations(); for (AnnotationDescription annotationDescription : declaredAnnotations.subList(annotationIndex, declaredAnnotations.size())) { annotationAppender = annotationAppender.append(annotationDescription, annotationValueFilter); } } } }
An attribute appender that appends a single annotation to a given type. The visibility for the annotation will be inferred from the annotation's RetentionPolicy.
/** * An attribute appender that appends a single annotation to a given type. The visibility for the annotation * will be inferred from the annotation's {@link java.lang.annotation.RetentionPolicy}. */
@HashCodeAndEqualsPlugin.Enhance class Explicit implements TypeAttributeAppender {
The annotations to write to the given type.
/** * The annotations to write to the given type. */
private final List<? extends AnnotationDescription> annotations;
Creates a new annotation attribute appender for explicit annotation values.
Params:
  • annotations – The annotations to write to the given type.
/** * Creates a new annotation attribute appender for explicit annotation values. * * @param annotations The annotations to write to the given type. */
public Explicit(List<? extends AnnotationDescription> annotations) { this.annotations = annotations; }
{@inheritDoc}
/** * {@inheritDoc} */
public void apply(ClassVisitor classVisitor, TypeDescription instrumentedType, AnnotationValueFilter annotationValueFilter) { AnnotationAppender appender = new AnnotationAppender.Default(new AnnotationAppender.Target.OnType(classVisitor)); for (AnnotationDescription annotation : annotations) { appender = appender.append(annotation, annotationValueFilter); } } }
A compound type attribute appender that concatenates a number of other attribute appenders.
/** * A compound type attribute appender that concatenates a number of other attribute appenders. */
@HashCodeAndEqualsPlugin.Enhance class Compound implements TypeAttributeAppender {
The type attribute appenders this compound appender represents in their application order.
/** * The type attribute appenders this compound appender represents in their application order. */
private final List<TypeAttributeAppender> typeAttributeAppenders;
Creates a new compound attribute appender.
Params:
  • typeAttributeAppender – The type attribute appenders to concatenate in the order of their application.
/** * Creates a new compound attribute appender. * * @param typeAttributeAppender The type attribute appenders to concatenate in the order of their application. */
public Compound(TypeAttributeAppender... typeAttributeAppender) { this(Arrays.asList(typeAttributeAppender)); }
Creates a new compound attribute appender.
Params:
  • typeAttributeAppenders – The type attribute appenders to concatenate in the order of their application.
/** * Creates a new compound attribute appender. * * @param typeAttributeAppenders The type attribute appenders to concatenate in the order of their application. */
public Compound(List<? extends TypeAttributeAppender> typeAttributeAppenders) { this.typeAttributeAppenders = new ArrayList<TypeAttributeAppender>(); for (TypeAttributeAppender typeAttributeAppender : typeAttributeAppenders) { if (typeAttributeAppender instanceof Compound) { this.typeAttributeAppenders.addAll(((Compound) typeAttributeAppender).typeAttributeAppenders); } else if (!(typeAttributeAppender instanceof NoOp)) { this.typeAttributeAppenders.add(typeAttributeAppender); } } }
{@inheritDoc}
/** * {@inheritDoc} */
public void apply(ClassVisitor classVisitor, TypeDescription instrumentedType, AnnotationValueFilter annotationValueFilter) { for (TypeAttributeAppender typeAttributeAppender : typeAttributeAppenders) { typeAttributeAppender.apply(classVisitor, instrumentedType, annotationValueFilter); } } } }