Skip to content

Commit 991595a

Browse files
committed
Avoid null pointer exception on non-present annotations.
1 parent 81c8c56 commit 991595a

12 files changed

Lines changed: 125 additions & 7 deletions

byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationList.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,24 @@ public ForLoadedAnnotations(Annotation... annotation) {
233233
}
234234

235235
/**
236-
* Creates a new list of loaded annotations.
236+
* Creates a new list of loaded annotations. Any {@code null} entries are filtered out as the JVM's
237+
* reflection API can return {@code null} for annotations whose annotation type is not available on
238+
* the class path.
237239
*
238240
* @param annotations The represented annotations.
239241
*/
240242
public ForLoadedAnnotations(List<? extends Annotation> annotations) {
241-
this.annotations = annotations;
243+
List<Annotation> resolved = null;
244+
for (int index = 0; index < annotations.size(); index++) {
245+
if (annotations.get(index) == null) {
246+
if (resolved == null) {
247+
resolved = new ArrayList<Annotation>(annotations.subList(0, index));
248+
}
249+
} else if (resolved != null) {
250+
resolved.add(annotations.get(index));
251+
}
252+
}
253+
this.annotations = resolved == null ? annotations : resolved;
242254
}
243255

244256
/**

byte-buddy-dep/src/main/java/net/bytebuddy/utility/AnnotationComparator.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package net.bytebuddy.utility;
1717

18+
import net.bytebuddy.utility.nullability.MaybeNull;
19+
1820
import java.lang.annotation.Annotation;
1921
import java.util.Comparator;
2022

@@ -31,9 +33,13 @@ public enum AnnotationComparator implements Comparator<Annotation> {
3133
/**
3234
* {@inheritDoc}
3335
*/
34-
public int compare(Annotation left, Annotation right) {
36+
public int compare(@MaybeNull Annotation left, @MaybeNull Annotation right) {
3537
if (left == right) {
3638
return 0;
39+
} else if (left == null) {
40+
return 1;
41+
} else if (right == null) {
42+
return -1;
3743
}
3844
return left.annotationType().getName().compareTo(right.annotationType().getName());
3945
}

byte-buddy-dep/src/main/java/net/bytebuddy/utility/ConstructorComparator.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package net.bytebuddy.utility;
1717

18+
import net.bytebuddy.utility.nullability.MaybeNull;
19+
1820
import java.lang.reflect.Constructor;
1921
import java.util.Comparator;
2022

@@ -31,9 +33,13 @@ public enum ConstructorComparator implements Comparator<Constructor<?>> {
3133
/**
3234
* {@inheritDoc}
3335
*/
34-
public int compare(Constructor<?> left, Constructor<?> right) {
36+
public int compare(@MaybeNull Constructor<?> left, @MaybeNull Constructor<?> right) {
3537
if (left == right) {
3638
return 0;
39+
} else if (left == null) {
40+
return 1;
41+
} else if (right == null) {
42+
return -1;
3743
}
3844
int comparison = left.getName().compareTo(right.getName());
3945
if (comparison == 0) {

byte-buddy-dep/src/main/java/net/bytebuddy/utility/FieldComparator.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package net.bytebuddy.utility;
1717

18+
import net.bytebuddy.utility.nullability.MaybeNull;
19+
1820
import java.lang.reflect.Field;
1921
import java.util.Comparator;
2022

@@ -31,9 +33,13 @@ public enum FieldComparator implements Comparator<Field> {
3133
/**
3234
* {@inheritDoc}
3335
*/
34-
public int compare(Field left, Field right) {
36+
public int compare(@MaybeNull Field left, @MaybeNull Field right) {
3537
if (left == right) {
3638
return 0;
39+
} else if (left == null) {
40+
return 1;
41+
} else if (right == null) {
42+
return -1;
3743
}
3844
int comparison = left.getName().compareTo(right.getName());
3945
if (comparison == 0) {

byte-buddy-dep/src/main/java/net/bytebuddy/utility/MethodComparator.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package net.bytebuddy.utility;
1717

18+
import net.bytebuddy.utility.nullability.MaybeNull;
19+
1820
import java.lang.reflect.Method;
1921
import java.util.Comparator;
2022

@@ -31,9 +33,13 @@ public enum MethodComparator implements Comparator<Method> {
3133
/**
3234
* {@inheritDoc}
3335
*/
34-
public int compare(Method left, Method right) {
36+
public int compare(@MaybeNull Method left, @MaybeNull Method right) {
3537
if (left == right) {
3638
return 0;
39+
} else if (left == null) {
40+
return 1;
41+
} else if (right == null) {
42+
return -1;
3743
}
3844
int comparison = left.getName().compareTo(right.getName());
3945
if (comparison == 0) {

byte-buddy-dep/src/main/java/net/bytebuddy/utility/TypeComparator.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package net.bytebuddy.utility;
1717

18+
import net.bytebuddy.utility.nullability.MaybeNull;
19+
1820
import java.util.Comparator;
1921

2022
/**
@@ -30,9 +32,13 @@ public enum TypeComparator implements Comparator<Class<?>> {
3032
/**
3133
* {@inheritDoc}
3234
*/
33-
public int compare(Class<?> left, Class<?> right) {
35+
public int compare(@MaybeNull Class<?> left, @MaybeNull Class<?> right) {
3436
if (left == right) {
3537
return 0;
38+
} else if (left == null) {
39+
return 1;
40+
} else if (right == null) {
41+
return -1;
3642
}
3743
return left.getName().compareTo(right.getName());
3844
}

byte-buddy-dep/src/test/java/net/bytebuddy/description/annotation/AnnotationListForLoadedAnnotationsTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
package net.bytebuddy.description.annotation;
22

3+
import org.junit.Test;
4+
35
import java.lang.annotation.Annotation;
6+
import java.util.Arrays;
7+
import java.util.Collections;
48
import java.util.List;
59

10+
import static org.hamcrest.CoreMatchers.is;
11+
import static org.hamcrest.MatcherAssert.assertThat;
12+
613
public class AnnotationListForLoadedAnnotationsTest extends AbstractAnnotationListTest<Annotation> {
714

815
protected Annotation getFirst() throws Exception {
@@ -20,4 +27,38 @@ protected AnnotationList asList(List<Annotation> elements) {
2027
protected AnnotationDescription asElement(Annotation element) {
2128
return new AnnotationDescription.ForLoadedAnnotation<Annotation>(element);
2229
}
30+
31+
@Test
32+
public void testFiltersNullEntriesFromArray() throws Exception {
33+
AnnotationList list = new AnnotationList.ForLoadedAnnotations(getFirst(), null, getSecond());
34+
assertThat(list.size(), is(2));
35+
assertThat(list.isAnnotationPresent(Foo.class), is(true));
36+
assertThat(list.isAnnotationPresent(Bar.class), is(true));
37+
}
38+
39+
@Test
40+
public void testFiltersNullEntriesFromList() throws Exception {
41+
AnnotationList list = new AnnotationList.ForLoadedAnnotations(Arrays.asList(getFirst(), null, getSecond()));
42+
assertThat(list.size(), is(2));
43+
assertThat(list.isAnnotationPresent(Foo.class), is(true));
44+
assertThat(list.isAnnotationPresent(Bar.class), is(true));
45+
}
46+
47+
@Test
48+
public void testAllNullEntriesYieldEmptyList() throws Exception {
49+
AnnotationList list = new AnnotationList.ForLoadedAnnotations(Arrays.<Annotation>asList(null, null));
50+
assertThat(list.size(), is(0));
51+
}
52+
53+
@Test
54+
public void testNullArrayEntriesAreFiltered() throws Exception {
55+
AnnotationList list = new AnnotationList.ForLoadedAnnotations(new Annotation[]{null});
56+
assertThat(list.size(), is(0));
57+
}
58+
59+
@Test
60+
public void testEmptyListIsPreserved() throws Exception {
61+
AnnotationList list = new AnnotationList.ForLoadedAnnotations(Collections.<Annotation>emptyList());
62+
assertThat(list.size(), is(0));
63+
}
2364
}

byte-buddy-dep/src/test/java/net/bytebuddy/utility/AnnotationComparatorTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,11 @@ public void testTypeComparison() {
2929
assertThat(AnnotationComparator.INSTANCE.compare(left, right) < 0, is(true));
3030
assertThat(AnnotationComparator.INSTANCE.compare(right, left) > 0, is(true));
3131
}
32+
33+
@Test
34+
public void testNullSafe() {
35+
assertThat(AnnotationComparator.INSTANCE.compare(null, null) == 0, is(true));
36+
assertThat(AnnotationComparator.INSTANCE.compare(null, right) > 0, is(true));
37+
assertThat(AnnotationComparator.INSTANCE.compare(left, null) < 0, is(true));
38+
}
3239
}

byte-buddy-dep/src/test/java/net/bytebuddy/utility/ConstructorComparatorTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ public void testComparisonSingleSingle() throws Exception {
3737
Sample.class.getDeclaredConstructor(String.class)), is(-10));
3838
}
3939

40+
@Test
41+
public void testNullSafe() throws Exception {
42+
assertThat(ConstructorComparator.INSTANCE.compare(null, null) == 0, is(true));
43+
assertThat(ConstructorComparator.INSTANCE.compare(null, Sample.class.getDeclaredConstructor()) > 0, is(true));
44+
assertThat(ConstructorComparator.INSTANCE.compare(Sample.class.getDeclaredConstructor(), null) < 0, is(true));
45+
}
46+
4047
@SuppressWarnings("unused")
4148
private static class Sample {
4249

byte-buddy-dep/src/test/java/net/bytebuddy/utility/FieldComparatorTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ public void testComparisonDifferent() throws Exception {
2424
Sample.class.getDeclaredField("first")), is(13));
2525
}
2626

27+
@Test
28+
public void testNullSafe() throws Exception {
29+
assertThat(FieldComparator.INSTANCE.compare(null, null) == 0, is(true));
30+
assertThat(FieldComparator.INSTANCE.compare(null, Sample.class.getDeclaredField("first")) > 0, is(true));
31+
assertThat(FieldComparator.INSTANCE.compare(Sample.class.getDeclaredField("first"), null) < 0, is(true));
32+
}
33+
2734
@SuppressWarnings("unused")
2835
private static class Sample {
2936

0 commit comments

Comments
 (0)