Skip to content

Commit 11c76cc

Browse files
committed
Add annotation removal.
1 parent 41016d9 commit 11c76cc

File tree

3 files changed

+372
-21
lines changed

3 files changed

+372
-21
lines changed
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
package net.bytebuddy.asm;
2+
3+
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
4+
import net.bytebuddy.description.annotation.AnnotationDescription;
5+
import net.bytebuddy.description.field.FieldDescription;
6+
import net.bytebuddy.description.field.FieldList;
7+
import net.bytebuddy.description.method.MethodDescription;
8+
import net.bytebuddy.description.method.MethodList;
9+
import net.bytebuddy.description.method.ParameterDescription;
10+
import net.bytebuddy.description.type.TypeDescription;
11+
import net.bytebuddy.implementation.Implementation;
12+
import net.bytebuddy.matcher.ElementMatcher;
13+
import net.bytebuddy.pool.TypePool;
14+
import net.bytebuddy.utility.CompoundList;
15+
import net.bytebuddy.utility.OpenedClassReader;
16+
import net.bytebuddy.utility.nullability.MaybeNull;
17+
import org.objectweb.asm.AnnotationVisitor;
18+
import org.objectweb.asm.ClassVisitor;
19+
import org.objectweb.asm.FieldVisitor;
20+
import org.objectweb.asm.MethodVisitor;
21+
22+
import java.util.Collections;
23+
import java.util.HashMap;
24+
import java.util.Map;
25+
26+
import static net.bytebuddy.matcher.ElementMatchers.*;
27+
28+
/**
29+
* A visitor wrapper that removes annotations from the instrumented type.
30+
*/
31+
@HashCodeAndEqualsPlugin.Enhance
32+
public class AnnotationRemoval extends AsmVisitorWrapper.AbstractBase {
33+
34+
private final boolean type;
35+
36+
private final ElementMatcher<? super FieldDescription.InDefinedShape> fieldMatcher;
37+
38+
private final ElementMatcher<? super MethodDescription> methodMatcher;
39+
40+
private final ElementMatcher<? super AnnotationDescription> annotationMatcher;
41+
42+
protected AnnotationRemoval(boolean type,
43+
ElementMatcher<? super FieldDescription.InDefinedShape.InDefinedShape> fieldMatcher,
44+
ElementMatcher<? super MethodDescription> methodMatcher,
45+
ElementMatcher<? super AnnotationDescription> annotationMatcher) {
46+
this.type = type;
47+
this.fieldMatcher = fieldMatcher;
48+
this.methodMatcher = methodMatcher;
49+
this.annotationMatcher = annotationMatcher;
50+
}
51+
52+
public static AnnotationRemoval strip(ElementMatcher<? super AnnotationDescription> matcher) {
53+
return new AnnotationRemoval(true, any(), any(), matcher);
54+
}
55+
56+
public AsmVisitorWrapper onType() {
57+
return new AnnotationRemoval(true, none(), none(), annotationMatcher);
58+
}
59+
60+
public AsmVisitorWrapper onFields(ElementMatcher<? super FieldDescription> matcher) {
61+
return new AnnotationRemoval(false, matcher, none(), annotationMatcher);
62+
}
63+
64+
public AsmVisitorWrapper onMethods(ElementMatcher<? super MethodDescription> matcher) {
65+
return onInvokables(isMethod().and(matcher));
66+
}
67+
68+
public AsmVisitorWrapper onConstructors(ElementMatcher<? super MethodDescription> matcher) {
69+
return onInvokables(isConstructor().and(matcher));
70+
}
71+
72+
public AsmVisitorWrapper onInvokables(ElementMatcher<? super MethodDescription> matcher) {
73+
return new AnnotationRemoval(false, none(), matcher, annotationMatcher);
74+
}
75+
76+
@Override
77+
public ClassVisitor wrap(TypeDescription instrumentedType,
78+
ClassVisitor classVisitor,
79+
Implementation.Context implementationContext,
80+
TypePool typePool,
81+
FieldList<FieldDescription.InDefinedShape> fields,
82+
MethodList<?> methods,
83+
int writerFlags,
84+
int readerFlags) {
85+
Map<String, AnnotationDescription> mappedAnnotations = new HashMap<String, AnnotationDescription>();
86+
if (type) {
87+
for (AnnotationDescription annotation : instrumentedType.getDeclaredAnnotations()) {
88+
mappedAnnotations.put(annotation.getAnnotationType().getDescriptor(), annotation);
89+
}
90+
}
91+
Map<String, FieldDescription.InDefinedShape> mappedFields = new HashMap<String, FieldDescription.InDefinedShape>();
92+
for (FieldDescription.InDefinedShape fieldDescription : fields) {
93+
mappedFields.put(fieldDescription.getInternalName() + fieldDescription.getDescriptor(), fieldDescription);
94+
}
95+
Map<String, MethodDescription> mappedMethods = new HashMap<String, MethodDescription>();
96+
for (MethodDescription methodDescription : CompoundList.<MethodDescription>of(methods, new MethodDescription.Latent.TypeInitializer(instrumentedType))) {
97+
mappedMethods.put(methodDescription.getInternalName() + methodDescription.getDescriptor(), methodDescription);
98+
}
99+
return new AnnotationRemovingClassVisitor(classVisitor, fieldMatcher, methodMatcher, annotationMatcher, mappedFields, mappedMethods, mappedAnnotations);
100+
}
101+
102+
private static class AnnotationRemovingClassVisitor extends ClassVisitor {
103+
104+
private final ElementMatcher<? super FieldDescription.InDefinedShape> fieldMatcher;
105+
106+
private final ElementMatcher<? super MethodDescription> methodMatcher;
107+
108+
private final ElementMatcher<? super AnnotationDescription> annotationMatcher;
109+
110+
private final Map<String, FieldDescription.InDefinedShape> fields;
111+
112+
private final Map<String, MethodDescription> methods;
113+
114+
private final Map<String, AnnotationDescription> annotations;
115+
116+
private AnnotationRemovingClassVisitor(ClassVisitor classVisitor,
117+
ElementMatcher<? super FieldDescription.InDefinedShape> fieldMatcher,
118+
ElementMatcher<? super MethodDescription> methodMatcher,
119+
ElementMatcher<? super AnnotationDescription> annotationMatcher,
120+
Map<String, FieldDescription.InDefinedShape> fields,
121+
Map<String, MethodDescription> methods,
122+
Map<String, AnnotationDescription> annotations) {
123+
super(OpenedClassReader.ASM_API, classVisitor);
124+
this.fieldMatcher = fieldMatcher;
125+
this.methodMatcher = methodMatcher;
126+
this.annotationMatcher = annotationMatcher;
127+
this.fields = fields;
128+
this.methods = methods;
129+
this.annotations = annotations;
130+
}
131+
132+
@Override
133+
@MaybeNull
134+
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
135+
AnnotationDescription annotation = annotations.get(descriptor);
136+
return annotation != null && annotationMatcher.matches(annotation)
137+
? null
138+
: super.visitAnnotation(descriptor, visible);
139+
}
140+
141+
@Override
142+
@MaybeNull
143+
public FieldVisitor visitField(int modifiers, String internalName, String descriptor, String signature, Object value) {
144+
FieldVisitor fieldVisitor = super.visitField(modifiers, internalName, descriptor, signature, value);
145+
if (fieldVisitor == null) {
146+
return null;
147+
}
148+
FieldDescription.InDefinedShape fieldDescription = fields.get(internalName + descriptor);
149+
if (fieldDescription != null && fieldMatcher.matches(fieldDescription)) {
150+
Map<String, AnnotationDescription> mappedAnnotations = new HashMap<String, AnnotationDescription>();
151+
for (AnnotationDescription annotation : fieldDescription.getDeclaredAnnotations()) {
152+
mappedAnnotations.put(annotation.getAnnotationType().getDescriptor(), annotation);
153+
}
154+
return new AnnotationRemovingFieldVisitor(fieldVisitor, annotationMatcher, mappedAnnotations);
155+
} else {
156+
return fieldVisitor;
157+
}
158+
}
159+
160+
@Override
161+
@MaybeNull
162+
public MethodVisitor visitMethod(int modifiers, String internalName, String descriptor, String signature, String[] exception) {
163+
MethodVisitor methodVisitor = super.visitMethod(modifiers, internalName, descriptor, signature, exception);
164+
if (methodVisitor == null) {
165+
return null;
166+
}
167+
MethodDescription methodDescription = methods.get(internalName + descriptor);
168+
if (methodDescription != null && methodMatcher.matches(methodDescription)) {
169+
Map<Integer, Map<String, AnnotationDescription>> mappedParameterAnnotations = new HashMap<Integer, Map<String, AnnotationDescription>>();
170+
for (ParameterDescription parameter : methodDescription.getParameters()) {
171+
Map<String, AnnotationDescription> mappedAnnotations = new HashMap<String, AnnotationDescription>();
172+
for (AnnotationDescription annotation : methodDescription.getDeclaredAnnotations()) {
173+
mappedAnnotations.put(annotation.getAnnotationType().getDescriptor(), annotation);
174+
}
175+
mappedParameterAnnotations.put(parameter.getIndex(), mappedAnnotations);
176+
}
177+
Map<String, AnnotationDescription> mappedAnnotations = new HashMap<String, AnnotationDescription>();
178+
for (AnnotationDescription annotation : methodDescription.getDeclaredAnnotations()) {
179+
mappedAnnotations.put(annotation.getAnnotationType().getDescriptor(), annotation);
180+
}
181+
return new AnnotationRemovingMethodVisitor(methodVisitor, annotationMatcher, mappedParameterAnnotations, mappedAnnotations);
182+
} else {
183+
return methodVisitor;
184+
}
185+
}
186+
}
187+
188+
private static class AnnotationRemovingFieldVisitor extends FieldVisitor {
189+
190+
private final ElementMatcher<? super AnnotationDescription> annotationMatcher;
191+
192+
private final Map<String, AnnotationDescription> annotations;
193+
194+
private AnnotationRemovingFieldVisitor(FieldVisitor fieldVisitor,
195+
ElementMatcher<? super AnnotationDescription> annotationMatcher,
196+
Map<String, AnnotationDescription> annotations) {
197+
super(OpenedClassReader.ASM_API, fieldVisitor);
198+
this.annotationMatcher = annotationMatcher;
199+
this.annotations = annotations;
200+
}
201+
202+
@Override
203+
@MaybeNull
204+
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
205+
AnnotationDescription annotation = annotations.get(descriptor);
206+
return annotation != null && annotationMatcher.matches(annotation)
207+
? null
208+
: super.visitAnnotation(descriptor, visible);
209+
}
210+
}
211+
212+
private static class AnnotationRemovingMethodVisitor extends MethodVisitor {
213+
214+
private final ElementMatcher<? super AnnotationDescription> annotationMatcher;
215+
216+
private final Map<Integer, Map<String, AnnotationDescription>> parameterAnnotations;
217+
218+
private final Map<String, AnnotationDescription> annotations;
219+
220+
private AnnotationRemovingMethodVisitor(MethodVisitor methodVisitor,
221+
ElementMatcher<? super AnnotationDescription> annotationMatcher,
222+
Map<Integer, Map<String, AnnotationDescription>> parameterAnnotations,
223+
Map<String, AnnotationDescription> annotations) {
224+
super(OpenedClassReader.ASM_API, methodVisitor);
225+
this.annotationMatcher = annotationMatcher;
226+
this.parameterAnnotations = parameterAnnotations;
227+
this.annotations = annotations;
228+
}
229+
230+
@Override
231+
@MaybeNull
232+
public AnnotationVisitor visitParameterAnnotation(int parameter, String descriptor, boolean visible) {
233+
AnnotationDescription annotation = parameterAnnotations
234+
.getOrDefault(parameter, Collections.<String, AnnotationDescription>emptyMap())
235+
.get(descriptor);
236+
return annotation != null && annotationMatcher.matches(annotation)
237+
? null
238+
: super.visitParameterAnnotation(parameter, descriptor, visible);
239+
}
240+
241+
@Override
242+
@MaybeNull
243+
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
244+
AnnotationDescription annotation = annotations.get(descriptor);
245+
return annotation != null && annotationMatcher.matches(annotation)
246+
? null
247+
: super.visitAnnotation(descriptor, visible);
248+
}
249+
}
250+
}

byte-buddy-dep/src/main/java/net/bytebuddy/asm/MemberRemoval.java

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import net.bytebuddy.pool.TypePool;
2828
import net.bytebuddy.utility.CompoundList;
2929
import net.bytebuddy.utility.OpenedClassReader;
30-
import net.bytebuddy.utility.nullability.AlwaysNull;
3130
import net.bytebuddy.utility.nullability.MaybeNull;
3231
import org.objectweb.asm.ClassVisitor;
3332
import org.objectweb.asm.FieldVisitor;
@@ -152,19 +151,7 @@ public ClassVisitor wrap(TypeDescription instrumentedType,
152151
/**
153152
* A class visitor that removes members based on element matchers.
154153
*/
155-
protected static class MemberRemovingClassVisitor extends ClassVisitor {
156-
157-
/**
158-
* Indicates the removal of a field.
159-
*/
160-
@javax.annotation.Nonnull(when = javax.annotation.meta.When.NEVER)
161-
private static final FieldVisitor REMOVE_FIELD = null;
162-
163-
/**
164-
* Indicates the removal of a method.
165-
*/
166-
@AlwaysNull
167-
private static final MethodVisitor REMOVE_METHOD = null;
154+
private static class MemberRemovingClassVisitor extends ClassVisitor {
168155

169156
/**
170157
* The matcher that determines field removal.
@@ -195,11 +182,11 @@ protected static class MemberRemovingClassVisitor extends ClassVisitor {
195182
* @param fields A mapping of field names and descriptors to their description.
196183
* @param methods A mapping of method names and descriptors to their description.
197184
*/
198-
protected MemberRemovingClassVisitor(ClassVisitor classVisitor,
199-
ElementMatcher.Junction<FieldDescription.InDefinedShape> fieldMatcher,
200-
ElementMatcher.Junction<MethodDescription> methodMatcher,
201-
Map<String, FieldDescription.InDefinedShape> fields,
202-
Map<String, MethodDescription> methods) {
185+
private MemberRemovingClassVisitor(ClassVisitor classVisitor,
186+
ElementMatcher.Junction<FieldDescription.InDefinedShape> fieldMatcher,
187+
ElementMatcher.Junction<MethodDescription> methodMatcher,
188+
Map<String, FieldDescription.InDefinedShape> fields,
189+
Map<String, MethodDescription> methods) {
203190
super(OpenedClassReader.ASM_API, classVisitor);
204191
this.fieldMatcher = fieldMatcher;
205192
this.methodMatcher = methodMatcher;
@@ -212,7 +199,7 @@ protected MemberRemovingClassVisitor(ClassVisitor classVisitor,
212199
public FieldVisitor visitField(int modifiers, String internalName, String descriptor, @MaybeNull String signature, @MaybeNull Object value) {
213200
FieldDescription.InDefinedShape fieldDescription = fields.get(internalName + descriptor);
214201
return fieldDescription != null && fieldMatcher.matches(fieldDescription)
215-
? REMOVE_FIELD
202+
? null
216203
: super.visitField(modifiers, internalName, descriptor, signature, value);
217204
}
218205

@@ -221,7 +208,7 @@ public FieldVisitor visitField(int modifiers, String internalName, String descri
221208
public MethodVisitor visitMethod(int modifiers, String internalName, String descriptor, @MaybeNull String signature, @MaybeNull String[] exception) {
222209
MethodDescription methodDescription = methods.get(internalName + descriptor);
223210
return methodDescription != null && methodMatcher.matches(methodDescription)
224-
? REMOVE_METHOD
211+
? null
225212
: super.visitMethod(modifiers, internalName, descriptor, signature, exception);
226213
}
227214
}

0 commit comments

Comments
 (0)